34 #include <opencv2/imgproc/types_c.h> 36 #ifdef RTABMAP_REALSENSE2 37 #include <librealsense2/rsutil.h> 38 #include <librealsense2/hpp/rs_processing.hpp> 39 #include <librealsense2/rs_advanced_mode.hpp> 48 #ifdef RTABMAP_REALSENSE2 56 const std::string &
device,
59 Camera(imageRate, localTransform)
60 #ifdef RTABMAP_REALSENSE2
63 depth_scale_meters_(1.0
f),
65 clockSyncWarningShown_(
false),
66 imuGlobalSyncWarningShown_(
false),
67 emitterEnabled_(
true),
71 odometryProvided_(
false),
72 odometryImagesDisabled_(
false),
73 odometryOnlyLeftStream_(
false),
77 cameraDepthWidth_(640),
78 cameraDepthHeight_(480),
80 globalTimeSync_(
true),
81 publishInterIMU_(
false),
91 #ifdef RTABMAP_REALSENSE2 96 #ifdef RTABMAP_REALSENSE2 97 void CameraRealSense2::close()
102 UDEBUG(
"Closing device(s)...");
103 for(
size_t i=0; i<dev_.size(); ++i)
105 UDEBUG(
"Closing %d sensor(s) from device %d...", (
int)dev_[i].query_sensors().size(), (
int)i);
106 for(rs2::sensor _sensor : dev_[i].query_sensors())
108 if(!_sensor.get_active_streams().empty())
115 catch(
const rs2::error & error)
117 UWARN(
"%s", error.what());
122 dev_[i].hardware_reset();
126 UDEBUG(
"Clearing devices...");
129 catch(
const rs2::error & error)
131 UINFO(
"%s", error.what());
137 void CameraRealSense2::imu_callback(rs2::frame frame)
139 auto stream = frame.get_profile().stream_type();
140 cv::Vec3f crnt_reading = *
reinterpret_cast<const cv::Vec3f*
>(frame.get_data());
141 UDEBUG(
"%s callback! %f (%f %f %f)",
142 stream == RS2_STREAM_GYRO?
"GYRO":
"ACC",
143 frame.get_timestamp(),
148 if(stream == RS2_STREAM_GYRO)
150 gyroBuffer_.insert(gyroBuffer_.end(), std::make_pair(frame.get_timestamp(), crnt_reading));
151 if(gyroBuffer_.size() > 1000)
153 gyroBuffer_.erase(gyroBuffer_.begin());
158 accBuffer_.insert(accBuffer_.end(), std::make_pair(frame.get_timestamp(), crnt_reading));
159 if(accBuffer_.size() > 1000)
161 accBuffer_.erase(accBuffer_.begin());
172 void CameraRealSense2::pose_callback(rs2::frame frame)
174 rs2_pose pose = frame.as<rs2::pose_frame>().get_pose_data();
188 poseBuffer_.insert(poseBuffer_.end(), std::make_pair(frame.get_timestamp(), std::make_pair(poseT, pose.tracker_confidence)));
189 if(poseBuffer_.size() > 1000)
191 poseBuffer_.erase(poseBuffer_.begin());
195 void CameraRealSense2::frame_callback(rs2::frame frame)
197 UDEBUG(
"Frame callback! %f", frame.get_timestamp());
200 void CameraRealSense2::multiple_message_callback(rs2::frame frame)
206 auto stream = frame.get_profile().stream_type();
209 case RS2_STREAM_GYRO:
210 case RS2_STREAM_ACCEL:
214 case RS2_STREAM_POSE:
216 if(odometryProvided_)
218 pose_callback(frame);
223 frame_callback(frame);
227 void CameraRealSense2::getPoseAndIMU(
228 const double & stamp,
230 unsigned int & poseConfidence,
239 if(!poseBuffer_.empty())
243 while(maxWaitTimeMs>0 && poseBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
250 if(poseBuffer_.rbegin()->first < stamp)
252 if(maxWaitTimeMs > 0)
254 UWARN(
"Could not find poses to interpolate at image time %f after waiting %d ms (last is %f)...", stamp/1000.0, maxWaitTimeMs, poseBuffer_.rbegin()->first/1000.0);
259 std::map<double, std::pair<Transform, unsigned int> >::const_iterator iterB = poseBuffer_.lower_bound(stamp);
260 std::map<double, std::pair<Transform, unsigned int> >::const_iterator iterA = iterB;
261 if(iterA != poseBuffer_.begin())
265 if(iterB == poseBuffer_.end())
269 if(iterA == iterB && stamp == iterA->first)
271 pose = iterA->second.first;
272 poseConfidence = iterA->second.second;
274 else if(stamp >= iterA->first && stamp <= iterB->first)
276 pose = iterA->second.first.
interpolate((stamp-iterA->first) / (iterB->first-iterA->first), iterB->second.first);
277 poseConfidence = iterA->second.second;
281 if(!imuGlobalSyncWarningShown_)
283 if(stamp < iterA->first)
285 UWARN(
"Could not find pose data to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0);
289 UWARN(
"Could not find pose data to interpolate at image time %f (between %f and %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0, iterB->first/1000.0);
294 if(!imuGlobalSyncWarningShown_)
296 UWARN(
"As globalTimeSync option is off, the received pose, gyro and accelerometer will be re-stamped with image time. This message is only shown once.");
297 imuGlobalSyncWarningShown_ =
true;
299 std::map<double, std::pair<Transform, unsigned int> >::const_reverse_iterator iterC = poseBuffer_.rbegin();
300 pose = iterC->second.first;
301 poseConfidence = iterC->second.second;
308 if(accBuffer_.empty() || gyroBuffer_.empty())
320 while(maxWaitTimeMs > 0 && accBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
328 if(globalTimeSync_ && accBuffer_.rbegin()->first < stamp)
332 UWARN(
"Could not find acc data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp/1000.0, maxWaitTimeMs, accBuffer_.rbegin()->first/1000.0);
339 std::map<double, cv::Vec3f>::const_iterator iterB = accBuffer_.lower_bound(stamp);
340 std::map<double, cv::Vec3f>::const_iterator iterA = iterB;
341 if(iterA != accBuffer_.begin())
345 if(iterB == accBuffer_.end())
349 if(iterA == iterB && stamp == iterA->first)
351 acc[0] = iterA->second[0];
352 acc[1] = iterA->second[1];
353 acc[2] = iterA->second[2];
355 else if(stamp >= iterA->first && stamp <= iterB->first)
357 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
358 acc[0] = iterA->second[0] + t*(iterB->second[0] - iterA->second[0]);
359 acc[1] = iterA->second[1] + t*(iterB->second[1] - iterA->second[1]);
360 acc[2] = iterA->second[2] + t*(iterB->second[2] - iterA->second[2]);
364 if(!imuGlobalSyncWarningShown_)
366 if(stamp < iterA->first)
368 UWARN(
"Could not find acc data to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0);
372 UWARN(
"Could not find acc data to interpolate at image time %f (between %f and %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0, iterB->first/1000.0);
377 if(!imuGlobalSyncWarningShown_)
379 UWARN(
"As globalTimeSync option is off, the received gyro and accelerometer will be re-stamped with image time. This message is only shown once.");
380 imuGlobalSyncWarningShown_ =
true;
382 std::map<double, cv::Vec3f>::const_reverse_iterator iterC = accBuffer_.rbegin();
383 acc[0] = iterC->second[0];
384 acc[1] = iterC->second[1];
385 acc[2] = iterC->second[2];
404 while(maxWaitTimeMs>0 && gyroBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
412 if(globalTimeSync_ && gyroBuffer_.rbegin()->first < stamp)
416 UWARN(
"Could not find gyro data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp/1000.0, maxWaitTimeMs, gyroBuffer_.rbegin()->first/1000.0);
423 std::map<double, cv::Vec3f>::const_iterator iterB = gyroBuffer_.lower_bound(stamp);
424 std::map<double, cv::Vec3f>::const_iterator iterA = iterB;
425 if(iterA != gyroBuffer_.begin())
429 if(iterB == gyroBuffer_.end())
433 if(iterA == iterB && stamp == iterA->first)
435 gyro[0] = iterA->second[0];
436 gyro[1] = iterA->second[1];
437 gyro[2] = iterA->second[2];
439 else if(stamp >= iterA->first && stamp <= iterB->first)
441 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
442 gyro[0] = iterA->second[0] + t*(iterB->second[0] - iterA->second[0]);
443 gyro[1] = iterA->second[1] + t*(iterB->second[1] - iterA->second[1]);
444 gyro[2] = iterA->second[2] + t*(iterB->second[2] - iterA->second[2]);
448 if(!imuGlobalSyncWarningShown_)
450 if(stamp < iterA->first)
452 UWARN(
"Could not find gyro data to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0);
456 UWARN(
"Could not find gyro data to interpolate at image time %f (between %f and %f). Are sensors synchronized?", stamp/1000.0, iterA->first/1000.0, iterB->first/1000.0);
461 if(!imuGlobalSyncWarningShown_)
463 UWARN(
"As globalTimeSync option is off, the latest received gyro and accelerometer will be re-stamped with image time. This message is only shown once.");
464 imuGlobalSyncWarningShown_ =
true;
466 std::map<double, cv::Vec3f>::const_reverse_iterator iterC = gyroBuffer_.rbegin();
467 gyro[0] = iterC->second[0];
468 gyro[1] = iterC->second[1];
469 gyro[2] = iterC->second[2];
481 imu =
IMU(gyro, cv::Mat::eye(3, 3, CV_64FC1), acc, cv::Mat::eye(3, 3, CV_64FC1), imuLocalTransform_);
488 #ifdef RTABMAP_REALSENSE2 490 UINFO(
"setupDevice...");
494 clockSyncWarningShown_ =
false;
495 imuGlobalSyncWarningShown_ =
false;
497 rs2::device_list list = ctx_.query_devices();
498 if (0 == list.size())
500 UERROR(
"No RealSense2 devices were found!");
509 auto sn = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
510 auto pid_str = dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID);
511 auto name = dev.get_info(RS2_CAMERA_INFO_NAME);
514 std::stringstream ss;
515 ss << std::hex << pid_str;
517 UINFO(
"Device \"%s\" with serial number %s was found with product ID=%d.",
name, sn, (
int)pid);
518 if(dualMode_ && pid == 0x0B37)
536 catch(
const rs2::error & error)
538 UWARN(
"%s. Is the camera already used with another app?", error.what());
543 if(dualMode_ && dev_.size()==2)
545 UERROR(
"Dual setup is enabled, but a D400 camera is not detected!");
550 UERROR(
"The requested device \"%s\" is NOT found!", deviceId_.c_str());
554 else if(dualMode_ && dev_.size()!=2)
556 UERROR(
"Dual setup is enabled, but a T265 camera is not detected!");
563 if (!jsonConfig_.empty())
565 if (dev_[0].is<rs400::advanced_mode>())
567 std::stringstream ss;
568 std::ifstream in(jsonConfig_);
572 std::string json_file_content = ss.str();
574 auto adv = dev_[0].as<rs400::advanced_mode>();
575 adv.load_json(json_file_content);
576 UINFO(
"JSON file is loaded! (%s)", jsonConfig_.c_str());
580 UWARN(
"JSON file provided doesn't exist! (%s)", jsonConfig_.c_str());
585 UWARN(
"A json config file is provided (%s), but device does not support advanced settings!", jsonConfig_.c_str());
589 ctx_.set_devices_changed_callback([
this](rs2::event_information& info)
591 for(
size_t i=0; i<dev_.size(); ++i)
593 if (info.was_removed(dev_[i]))
597 UDEBUG(
"The device %d has been disconnected!", i);
601 UERROR(
"The device %d has been disconnected!", i);
607 auto sn = dev_[0].get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
608 UINFO(
"Using device with Serial No: %s", sn);
610 auto camera_name = dev_[0].get_info(RS2_CAMERA_INFO_NAME);
611 UINFO(
"Device Name: %s", camera_name);
613 auto fw_ver = dev_[0].get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);
614 UINFO(
"Device FW version: %s", fw_ver);
616 auto pid = dev_[0].get_info(RS2_CAMERA_INFO_PRODUCT_ID);
617 UINFO(
"Device Product ID: 0x%s", pid);
619 auto dev_sensors = dev_[0].query_sensors();
623 auto dev_sensors2 = dev_[1].query_sensors();
624 dev_sensors.insert(dev_sensors.end(), dev_sensors2.begin(), dev_sensors2.end());
627 UINFO(
"Device Sensors: ");
628 std::vector<rs2::sensor> sensors(2);
631 for(
auto&& elem : dev_sensors)
633 std::string module_name = elem.get_info(RS2_CAMERA_INFO_NAME);
634 if (
"Stereo Module" == module_name)
637 sensors[1].set_option(rs2_option::RS2_OPTION_EMITTER_ENABLED, emitterEnabled_);
639 else if (
"Coded-Light Depth Sensor" == module_name)
642 else if (
"RGB Camera" == module_name)
649 else if (
"Wide FOV Camera" == module_name)
652 else if (
"Motion Module" == module_name)
660 else if (
"Tracking Module" == module_name)
671 sensors.back() = elem;
672 sensors.back().set_option(rs2_option::RS2_OPTION_ENABLE_POSE_JUMPING, 0);
673 sensors.back().set_option(rs2_option::RS2_OPTION_ENABLE_RELOCALIZATION, 0);
675 else if (
"L500 Depth Sensor" == module_name)
681 cameraWidth_ = cameraDepthWidth_;
682 cameraHeight_ = cameraDepthHeight_;
683 cameraFps_ = cameraDepthFps_;
689 UERROR(
"Module Name \"%s\" isn't supported!", module_name.c_str());
692 UINFO(
"%s was found.", elem.get_info(RS2_CAMERA_INFO_NAME));
698 std::vector<std::vector<rs2::stream_profile> > profilesPerSensor(sensors.size());
699 for (
unsigned int i=0; i<sensors.size(); ++i)
701 if(i==0 && ir_ && !stereo)
705 UINFO(
"Sensor %d \"%s\"", (
int)i, sensors[i].get_info(RS2_CAMERA_INFO_NAME));
706 auto profiles = sensors[i].get_stream_profiles();
708 UINFO(
"profiles=%d", (
int)profiles.size());
713 auto video_profile =
profile.as<rs2::video_stream_profile>();
714 UINFO(
"%s %d %d %d %d %s type=%d", rs2_format_to_string(
715 video_profile.format()),
716 video_profile.width(),
717 video_profile.height(),
719 video_profile.stream_index(),
720 video_profile.stream_name().c_str(),
721 video_profile.stream_type());
727 auto video_profile =
profile.as<rs2::video_stream_profile>();
730 if( (video_profile.width() == cameraWidth_ &&
731 video_profile.height() == cameraHeight_ &&
732 video_profile.fps() == cameraFps_) ||
733 (strcmp(sensors[i].get_info(RS2_CAMERA_INFO_NAME),
"L500 Depth Sensor")==0 &&
734 video_profile.width() == cameraDepthWidth_ &&
735 video_profile.height() == cameraDepthHeight_ &&
736 video_profile.fps() == cameraDepthFps_))
738 auto intrinsic = video_profile.get_intrinsics();
741 if((!ir_ && video_profile.format() == RS2_FORMAT_RGB8 && video_profile.stream_type() == RS2_STREAM_COLOR) ||
742 (ir_ && video_profile.format() == RS2_FORMAT_Y8 && (video_profile.stream_index() == 1 || isL500)))
744 if(!profilesPerSensor[i].empty())
747 profilesPerSensor[i].push_back(profilesPerSensor[i].back());
748 profilesPerSensor[i].front() =
profile;
752 profilesPerSensor[i].push_back(
profile);
754 rgbBuffer_ = cv::Mat(cv::Size(cameraWidth_, cameraHeight_), video_profile.format() == RS2_FORMAT_Y8?CV_8UC1:CV_8UC3, ir_?cv::Scalar(0):cv::Scalar(0, 0, 0));
755 model_ =
CameraModel(camera_name, intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy, this->getLocalTransform(), 0, cv::Size(intrinsic.width, intrinsic.height));
756 UINFO(
"Model: %dx%d fx=%f fy=%f cx=%f cy=%f dist model=%d coeff=%f %f %f %f %f",
757 intrinsic.width, intrinsic.height,
758 intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy,
760 intrinsic.coeffs[0], intrinsic.coeffs[1], intrinsic.coeffs[2], intrinsic.coeffs[3], intrinsic.coeffs[4]);
762 if(video_profile.format() == RS2_FORMAT_RGB8 || profilesPerSensor[i].size()==2)
768 else if(((!ir_ || irDepth_) && video_profile.format() == RS2_FORMAT_Z16) ||
769 (ir_ && !irDepth_ && video_profile.format() == RS2_FORMAT_Y8 && video_profile.stream_index() == 2))
771 profilesPerSensor[i].push_back(
profile);
772 depthBuffer_ = cv::Mat(cv::Size(cameraWidth_, cameraHeight_), video_profile.format() == RS2_FORMAT_Y8?CV_8UC1:CV_16UC1, cv::Scalar(0));
774 if(!ir_ || irDepth_ || profilesPerSensor[i].size()==2)
780 else if(video_profile.format() == RS2_FORMAT_MOTION_XYZ32F || video_profile.format() == RS2_FORMAT_6DOF)
791 bool modified =
false;
792 for (
size_t j= 0; j < profilesPerSensor[i].size(); ++j)
794 if (profilesPerSensor[i][j].stream_type() ==
profile.stream_type())
796 if (
profile.stream_type() == RS2_STREAM_ACCEL)
798 if(
profile.fps() > profilesPerSensor[i][j].fps())
799 profilesPerSensor[i][j] =
profile;
802 else if (
profile.stream_type() == RS2_STREAM_GYRO)
804 if(
profile.fps() < profilesPerSensor[i][j].fps())
805 profilesPerSensor[i][j] =
profile;
811 profilesPerSensor[i].push_back(
profile);
815 else if(stereo || dualMode_)
819 video_profile.format() == RS2_FORMAT_Y8 &&
820 video_profile.width() == 848 &&
821 video_profile.height() == 800 &&
822 video_profile.fps() == 30)
825 profilesPerSensor[i].push_back(
profile);
829 rgbBuffer_ = cv::Mat(cv::Size(848, 800), CV_8UC1, cv::Scalar(0));
830 if(odometryOnlyLeftStream_)
832 auto intrinsic = video_profile.get_intrinsics();
833 UINFO(
"Model: %dx%d fx=%f fy=%f cx=%f cy=%f dist model=%d coeff=%f %f %f %f",
834 intrinsic.width, intrinsic.height,
835 intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy,
837 intrinsic.coeffs[0], intrinsic.coeffs[1], intrinsic.coeffs[2], intrinsic.coeffs[3]);
838 cv::Mat K = cv::Mat::eye(3,3,CV_64FC1);
839 K.at<
double>(0,0) = intrinsic.fx;
840 K.at<
double>(1,1) = intrinsic.fy;
841 K.at<
double>(0,2) = intrinsic.ppx;
842 K.at<
double>(1,2) = intrinsic.ppy;
843 UASSERT(intrinsic.model == RS2_DISTORTION_KANNALA_BRANDT4);
844 cv::Mat D = cv::Mat::zeros(1,6,CV_64FC1);
845 D.at<
double>(0,0) = intrinsic.coeffs[0];
846 D.at<
double>(0,1) = intrinsic.coeffs[1];
847 D.at<
double>(0,4) = intrinsic.coeffs[2];
848 D.at<
double>(0,5) = intrinsic.coeffs[3];
849 cv::Mat
P = cv::Mat::eye(3, 4, CV_64FC1);
850 P.at<
double>(0,0) = intrinsic.fx;
851 P.at<
double>(1,1) = intrinsic.fy;
852 P.at<
double>(0,2) = intrinsic.ppx;
853 P.at<
double>(1,2) = intrinsic.ppy;
854 cv::Mat R = cv::Mat::eye(3, 3, CV_64FC1);
855 model_ =
CameraModel(camera_name, cv::Size(intrinsic.width, intrinsic.height), K, D, R, P, this->getLocalTransform());
860 else if(!odometryOnlyLeftStream_)
863 depthBuffer_ = cv::Mat(cv::Size(848, 800), CV_8UC1, cv::Scalar(0));
867 else if(video_profile.format() == RS2_FORMAT_MOTION_XYZ32F || video_profile.format() == RS2_FORMAT_6DOF)
872 profilesPerSensor[i].push_back(
profile);
880 UERROR(
"Given stream configuration is not supported by the device! " 881 "Stream Index: %d, Width: %d, Height: %d, FPS: %d", i, cameraWidth_, cameraHeight_, cameraFps_);
882 UERROR(
"Available configurations:");
885 auto video_profile =
profile.as<rs2::video_stream_profile>();
886 UERROR(
"%s %d %d %d %d %s type=%d", rs2_format_to_string(
887 video_profile.format()),
888 video_profile.width(),
889 video_profile.height(),
891 video_profile.stream_index(),
892 video_profile.stream_name().c_str(),
893 video_profile.stream_type());
901 if(!model_.isValidForProjection())
903 UERROR(
"Calibration info not valid!");
904 std::cout<< model_ << std::endl;
910 UINFO(
"Set base to pose");
912 UINFO(
"dualExtrinsics_ = %s", dualExtrinsics_.prettyPrint().c_str());
914 UASSERT(profilesPerSensor.size()>=2);
915 UASSERT(profilesPerSensor.back().size() == 3);
916 rs2_extrinsics poseToIMU = profilesPerSensor.back()[0].get_extrinsics_to(profilesPerSensor.back()[2]);
919 poseToIMU.rotation[0], poseToIMU.rotation[1], poseToIMU.rotation[2], poseToIMU.translation[0],
920 poseToIMU.rotation[3], poseToIMU.rotation[4], poseToIMU.rotation[5], poseToIMU.translation[1],
921 poseToIMU.rotation[6], poseToIMU.rotation[7], poseToIMU.rotation[8], poseToIMU.translation[2]);
922 poseToIMUT = realsense2PoseRotation_ * poseToIMUT;
923 UINFO(
"poseToIMU = %s", poseToIMUT.prettyPrint().c_str());
925 UINFO(
"BaseToCam = %s", baseToCam.prettyPrint().c_str());
926 model_.setLocalTransform(baseToCam);
930 if(ir_ && !irDepth_ && profilesPerSensor.size() >= 2 && profilesPerSensor[1].size() >= 2)
932 rs2_extrinsics leftToRight = profilesPerSensor[1][1].get_extrinsics_to(profilesPerSensor[1][0]);
934 leftToRight.rotation[0], leftToRight.rotation[1], leftToRight.rotation[2], leftToRight.translation[0],
935 leftToRight.rotation[3], leftToRight.rotation[4], leftToRight.rotation[5], leftToRight.translation[1],
936 leftToRight.rotation[6], leftToRight.rotation[7], leftToRight.rotation[8], leftToRight.translation[2]);
941 stereoModel_ =
StereoCameraModel(model_.fx(), model_.fy(), model_.cx(), model_.cy(), leftToRightT.
x(), model_.localTransform(), model_.imageSize());
942 UINFO(
"Stereo parameters: fx=%f cx=%f cy=%f baseline=%f",
943 stereoModel_.left().fx(),
944 stereoModel_.left().cx(),
945 stereoModel_.left().cy(),
946 stereoModel_.baseline());
949 if(!dualMode_ && profilesPerSensor.size() == 3)
951 if(!profilesPerSensor[2].empty() && !profilesPerSensor[0].empty())
953 rs2_extrinsics leftToIMU = profilesPerSensor[2][0].get_extrinsics_to(profilesPerSensor[0][0]);
955 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
956 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
957 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
959 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
961 else if(!profilesPerSensor[2].empty() && !profilesPerSensor[1].empty())
963 rs2_extrinsics leftToIMU = profilesPerSensor[2][0].get_extrinsics_to(profilesPerSensor[1][0]);
965 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
966 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
967 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
970 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
978 std::string serial = sn;
979 if(!cameraName.empty())
983 if(!odometryImagesDisabled_ &&
984 !odometryOnlyLeftStream_ &&
985 !calibrationFolder.empty() && !serial.empty())
987 if(!stereoModel_.load(calibrationFolder, serial,
false))
989 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
990 serial.c_str(), calibrationFolder.c_str());
994 UINFO(
"Stereo parameters: fx=%f cx=%f cy=%f baseline=%f",
995 stereoModel_.left().fx(),
996 stereoModel_.left().cx(),
997 stereoModel_.left().cy(),
998 stereoModel_.baseline());
1008 UASSERT(profilesPerSensor[0].size() == 5);
1009 if(odometryProvided_)
1011 rs2_extrinsics poseToLeft = profilesPerSensor[0][0].get_extrinsics_to(profilesPerSensor[0][4]);
1012 rs2_extrinsics poseToIMU = profilesPerSensor[0][2].get_extrinsics_to(profilesPerSensor[0][4]);
1014 poseToLeft.rotation[0], poseToLeft.rotation[1], poseToLeft.rotation[2], poseToLeft.translation[0],
1015 poseToLeft.rotation[3], poseToLeft.rotation[4], poseToLeft.rotation[5], poseToLeft.translation[1],
1016 poseToLeft.rotation[6], poseToLeft.rotation[7], poseToLeft.rotation[8], poseToLeft.translation[2]);
1017 poseToLeftT = realsense2PoseRotation_ * poseToLeftT;
1018 UINFO(
"poseToLeft = %s", poseToLeftT.prettyPrint().c_str());
1021 poseToIMU.rotation[0], poseToIMU.rotation[1], poseToIMU.rotation[2], poseToIMU.translation[0],
1022 poseToIMU.rotation[3], poseToIMU.rotation[4], poseToIMU.rotation[5], poseToIMU.translation[1],
1023 poseToIMU.rotation[6], poseToIMU.rotation[7], poseToIMU.rotation[8], poseToIMU.translation[2]);
1024 poseToIMUT = realsense2PoseRotation_ * poseToIMUT;
1025 UINFO(
"poseToIMU = %s", poseToIMUT.prettyPrint().c_str());
1027 Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
1029 if(odometryOnlyLeftStream_)
1035 if(odometryImagesDisabled_)
1038 std::vector<rs2::stream_profile> profiles;
1039 profiles.push_back(profilesPerSensor[0][4]);
1040 profilesPerSensor[0] = profiles;
1046 rs2_extrinsics leftToIMU = profilesPerSensor[0][2].get_extrinsics_to(profilesPerSensor[0][0]);
1048 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
1049 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
1050 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
1053 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
1054 if(odometryOnlyLeftStream_)
1059 if(!odometryImagesDisabled_ && rectifyImages_ && !model_.isValidForRectification() && !stereoModel_.isValidForRectification())
1061 UERROR(
"Parameter \"rectifyImages\" is set, but no stereo model is loaded or valid.");
1066 std::function<void(rs2::frame)> multiple_message_callback_function = [
this](rs2::frame frame){multiple_message_callback(frame);};
1068 for (
unsigned int i=0; i<sensors.size(); ++i)
1070 if(profilesPerSensor[i].size())
1072 UINFO(
"Starting sensor %d with %d profiles", (
int)i, (
int)profilesPerSensor[i].size());
1073 for (
size_t j = 0; j < profilesPerSensor[i].size(); ++j)
1075 auto video_profile = profilesPerSensor[i][j].as<rs2::video_stream_profile>();
1076 UINFO(
"Opening: %s %d %d %d %d %s type=%d", rs2_format_to_string(
1077 video_profile.format()),
1078 video_profile.width(),
1079 video_profile.height(),
1080 video_profile.fps(),
1081 video_profile.stream_index(),
1082 video_profile.stream_name().c_str(),
1083 video_profile.stream_type());
1085 if(globalTimeSync_ && sensors[i].supports(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED))
1087 float value = sensors[i].get_option(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED);
1088 UINFO(
"Set RS2_OPTION_GLOBAL_TIME_ENABLED=1 (was %f) for sensor %d", value, (
int)i);
1089 sensors[i].set_option(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED, 1);
1091 sensors[i].open(profilesPerSensor[i]);
1092 if(sensors[i].is<rs2::depth_sensor>())
1094 auto depth_sensor = sensors[i].as<rs2::depth_sensor>();
1095 depth_scale_meters_ = depth_sensor.get_depth_scale();
1096 UINFO(
"Depth scale %f for sensor %d", depth_scale_meters_, (
int)i);
1098 sensors[i].start(multiple_message_callback_function);
1103 UINFO(
"Enabling streams...done!");
1108 UERROR(
"CameraRealSense: RTAB-Map is not built with RealSense2 support!");
1115 #ifdef RTABMAP_REALSENSE2 1116 return model_.isValidForProjection() || stereoModel_.isValidForRectification();
1124 #ifdef RTABMAP_REALSENSE2 1127 return dev_[0].get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
1135 #ifdef RTABMAP_REALSENSE2 1136 return odometryProvided_;
1144 #ifdef RTABMAP_REALSENSE2 1146 unsigned int confidence = 0;
1147 double rsStamp = stamp*1000.0;
1149 getPoseAndIMU(rsStamp, p, confidence, imu);
1156 covariance = cv::Mat::eye(6,6,CV_64FC1) * 0.0001;
1157 covariance.rowRange(0,3) *=
pow(10, 3-(
int)confidence);
1158 covariance.rowRange(3,6) *=
pow(10, 1-(
int)confidence);
1167 #ifdef RTABMAP_REALSENSE2 1168 emitterEnabled_ = enabled;
1174 #ifdef RTABMAP_REALSENSE2 1176 irDepth_ = useDepthInsteadOfRightImage;
1182 #ifdef RTABMAP_REALSENSE2 1183 cameraWidth_ = width;
1184 cameraHeight_ = height;
1191 #ifdef RTABMAP_REALSENSE2 1192 cameraDepthWidth_ = width;
1193 cameraDepthHeight_ = height;
1194 cameraDepthFps_ = fps;
1200 #ifdef RTABMAP_REALSENSE2 1201 globalTimeSync_ = enabled;
1207 #ifdef RTABMAP_REALSENSE2 1208 publishInterIMU_ = enabled;
1214 #ifdef RTABMAP_REALSENSE2 1216 dualMode_ = enabled;
1220 odometryProvided_ =
true;
1221 odometryImagesDisabled_ =
false;
1222 odometryOnlyLeftStream_ =
false;
1229 #ifdef RTABMAP_REALSENSE2 1236 #ifdef RTABMAP_REALSENSE2 1237 rectifyImages_ = enabled;
1243 #ifdef RTABMAP_REALSENSE2 1244 if(dualMode_ && !enabled)
1246 UERROR(
"Odometry is disabled but dual mode was enabled, disabling dual mode.");
1249 odometryProvided_ = enabled;
1250 odometryImagesDisabled_ = enabled && imageStreamsDisabled;
1251 odometryOnlyLeftStream_ = enabled && !imageStreamsDisabled && onlyLeftStream;
1258 #ifdef RTABMAP_REALSENSE2 1261 auto frameset = syncer_.wait_for_frames(5000);
1263 int desiredFramesetSize = 2;
1264 while ((
int)frameset.size() != desiredFramesetSize && timer.
elapsed() < 2.0)
1267 frameset = syncer_.wait_for_frames(100);
1269 if ((
int)frameset.size() == desiredFramesetSize)
1272 bool is_rgb_arrived =
false;
1273 bool is_depth_arrived =
false;
1274 bool is_left_fisheye_arrived =
false;
1275 bool is_right_fisheye_arrived =
false;
1276 rs2::frame rgb_frame;
1277 rs2::frame depth_frame;
1278 double stamp = frameset.get_timestamp();
1279 for (
auto it = frameset.begin(); it != frameset.end(); ++it)
1282 if(stamp >
f.get_timestamp())
1284 stamp =
f.get_timestamp();
1286 auto stream_type =
f.get_profile().stream_type();
1287 if (stream_type == RS2_STREAM_COLOR || stream_type == RS2_STREAM_INFRARED)
1289 if(ir_ && !irDepth_)
1292 if(!is_depth_arrived)
1295 is_depth_arrived =
true;
1300 is_rgb_arrived =
true;
1306 is_rgb_arrived =
true;
1309 else if (stream_type == RS2_STREAM_DEPTH)
1312 is_depth_arrived =
true;
1314 else if (stream_type == RS2_STREAM_FISHEYE)
1316 if(!is_right_fisheye_arrived)
1319 is_right_fisheye_arrived =
true;
1324 is_left_fisheye_arrived =
true;
1330 UDEBUG(
"Frameset arrived. system=%fs frame=%fs", now, stamp);
1331 if(stamp - now > 1000000000.0)
1333 if(!clockSyncWarningShown_)
1335 UWARN(
"Clocks are not sync with host computer! Detected stamps in far " 1336 "future %f, thus using host time instead (%f)! This message " 1337 "will only appear once. " 1338 "See https://github.com/IntelRealSense/librealsense/issues/4505 " 1339 "for more info", stamp, now);
1340 clockSyncWarningShown_ =
true;
1345 if(is_rgb_arrived && is_depth_arrived)
1348 if(ir_ && !irDepth_)
1350 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()).clone();
1354 rs2::align align(rgb_frame.get_profile().stream_type());
1355 rs2::frameset processed = frameset.apply_filter(align);
1356 rs2::depth_frame aligned_depth_frame = processed.get_depth_frame();
1357 if(frameset.get_depth_frame().get_width() < aligned_depth_frame.get_width() &&
1358 frameset.get_depth_frame().get_height() < aligned_depth_frame.get_height())
1360 int decimationWidth = int(
float(aligned_depth_frame.get_width())/
float(frameset.get_depth_frame().get_width())+0.5
f);
1361 int decimationHeight = int(
float(aligned_depth_frame.get_height())/
float(frameset.get_depth_frame().get_height())+0.5
f);
1362 if(decimationWidth>1 || decimationHeight>1)
1364 depth =
util2d::decimate(cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)aligned_depth_frame.get_data()), decimationWidth>decimationHeight?decimationWidth:decimationHeight);
1368 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)aligned_depth_frame.get_data()).clone();
1373 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)aligned_depth_frame.get_data()).clone();
1375 if(depth_scale_meters_ != 0.001
f)
1377 if(depth.type() == CV_16UC1)
1379 float scaleMM = depth_scale_meters_ / 0.001f;
1380 depth = scaleMM * depth;
1385 cv::Mat rgb = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data());
1387 if(rgb.channels() == 3)
1389 cv::cvtColor(rgb, bgr, CV_RGB2BGR);
1396 if(ir_ && !irDepth_)
1406 else if(is_left_fisheye_arrived)
1408 if(odometryOnlyLeftStream_)
1411 if(rectifyImages_ && model_.isValidForRectification())
1413 left = model_.rectifyImage(cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()));
1417 left = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()).clone();
1420 if(model_.imageHeight() == 0 || model_.imageWidth() == 0)
1422 model_.setImageSize(left.size());
1427 else if(is_right_fisheye_arrived)
1430 if(rectifyImages_ && stereoModel_.left().isValidForRectification() && stereoModel_.right().isValidForRectification())
1432 left = stereoModel_.left().rectifyImage(cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()));
1433 right = stereoModel_.right().rectifyImage(cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()));
1437 left = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()).clone();
1438 right = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()).clone();
1441 if(stereoModel_.left().imageHeight() == 0 || stereoModel_.left().imageWidth() == 0)
1443 stereoModel_.setImageSize(left.size());
1451 UERROR(
"Not received depth and rgb");
1455 unsigned int confidence = 0;
1456 double imuStamp = stamp*1000.0;
1458 getPoseAndIMU(imuStamp, pose, confidence, imu);
1460 if(info && odometryProvided_ && !pose.
isNull())
1469 if(!imu.
empty() && !publishInterIMU_)
1473 else if(publishInterIMU_ && !gyroBuffer_.empty())
1475 if(lastImuStamp_ > 0.0)
1477 UASSERT(imuStamp > lastImuStamp_);
1479 std::map<double, cv::Vec3f>::iterator iterA = gyroBuffer_.upper_bound(lastImuStamp_);
1480 std::map<double, cv::Vec3f>::iterator iterB = gyroBuffer_.lower_bound(imuStamp);
1481 if(iterA != gyroBuffer_.end())
1485 if(iterB != gyroBuffer_.end())
1489 std::vector<double> stamps;
1490 for(;iterA != iterB;++iterA)
1492 stamps.push_back(iterA->first);
1497 for(
size_t i=0; i<stamps.size(); ++i)
1501 getPoseAndIMU(stamps[i], tmp, confidence, imuTmp);
1514 UDEBUG(
"inter imu published=%d (rate=%fHz), %f -> %f", pub,
double(pub)/((stamps.back()-stamps.front())/1000.0), stamps.front()/1000.0, stamps.back()/1000.0);
1518 UWARN(
"No inter imu published!?");
1521 lastImuStamp_ = imuStamp;
1524 else if(frameset.size()==1 && frameset[0].get_profile().stream_type() == RS2_STREAM_FISHEYE)
1526 UERROR(
"Missing frames (received %d, needed=%d). For T265 camera, " 1527 "either use realsense sdk v2.42.0, or apply " 1528 "this patch (https://github.com/IntelRealSense/librealsense/issues/9030#issuecomment-962223017) " 1529 "to fix this problem.", (
int)frameset.size(), desiredFramesetSize);
1533 UERROR(
"Missing frames (received %d, needed=%d)", (
int)frameset.size(), desiredFramesetSize);
1536 catch(
const std::exception& ex)
1538 UERROR(
"An error has occurred during frame callback: %s", ex.what());
1541 UERROR(
"CameraRealSense2: RTAB-Map is not built with RealSense2 support!");
std::string UTILITE_EXP uToUpperCase(const std::string &str)
constexpr T pow(const T base, const std::size_t exponent)
static void post(UEvent *event, bool async=true, const UEventsSender *sender=0)
void setDualMode(bool enabled, const Transform &extrinsics)
void setJsonConfig(const std::string &json)
void setImagesRectified(bool enabled)
virtual bool init(const std::string &calibrationFolder=".", const std::string &cameraName="")
void setEmitterEnabled(bool enabled)
virtual SensorData captureImage(CameraInfo *info=0)
Some conversion functions.
virtual bool odomProvided() const
static Transform opticalRotation()
bool uStrContains(const std::string &string, const std::string &substring)
void publishInterIMU(bool enabled)
virtual std::string getSerial() const
bool initRectificationMap()
#define UASSERT(condition)
Wrappers of STL for convenient functions.
cv::Mat RTABMAP_EXP decimate(const cv::Mat &image, int d)
GLM_FUNC_DECL genType pi()
const Transform & getLocalTransform() const
virtual bool isCalibrated() const
static ULogger::Level level()
virtual ~CameraRealSense2()
void setDepthResolution(int width, int height, int fps=30)
void uSleep(unsigned int ms)
CameraRealSense2(const std::string &deviceId="", float imageRate=0, const Transform &localTransform=Transform::getIdentity())
void setIRFormat(bool enabled, bool useDepthInsteadOfRightImage)
void setLocalTransform(const Transform &localTransform)
void setIMU(const IMU &imu)
void setOdomProvided(bool enabled, bool imageStreamsDisabled=false, bool onlyLeftStream=false)
void setResolution(int width, int height, int fps=30)
virtual bool getPose(double stamp, Transform &pose, cv::Mat &covariance)
void setGlobalTimeSync(bool enabled)
GLM_FUNC_DECL matType< T, P > inverse(matType< T, P > const &m)