32 #include <opencv2/imgproc/types_c.h> 34 #ifdef RTABMAP_REALSENSE2 35 #include <librealsense2/rs.hpp> 36 #include <librealsense2/rsutil.h> 37 #include <librealsense2/hpp/rs_processing.hpp> 38 #include <librealsense2/rs_advanced_mode.hpp> 47 #ifdef RTABMAP_REALSENSE2 55 const std::string &
device,
58 Camera(imageRate, localTransform)
59 #ifdef RTABMAP_REALSENSE2
61 ctx_(new
rs2::context),
64 syncer_(new
rs2::syncer),
65 depth_scale_meters_(1.0
f),
66 depthIntrinsics_(new rs2_intrinsics),
67 rgbIntrinsics_(new rs2_intrinsics),
68 depthToRGBExtrinsics_(new rs2_extrinsics),
70 clockSyncWarningShown_(
false),
71 imuGlobalSyncWarningShown_(
false),
72 emitterEnabled_(
true),
76 odometryProvided_(
false),
80 globalTimeSync_(
true),
81 publishInterIMU_(
false),
92 #ifdef RTABMAP_REALSENSE2 96 UDEBUG(
"Closing device(s)...");
97 for(
size_t i=0; i<dev_.size(); ++i)
101 UDEBUG(
"Closing %d sensor(s) from device %d...", (
int)dev_[i]->query_sensors().size(), (
int)i);
102 for(rs2::sensor _sensor : dev_[i]->query_sensors())
109 catch(
const rs2::error & error)
111 UWARN(
"%s", error.what());
114 dev_[i]->hardware_reset();
119 catch(
const rs2::error & error)
121 UINFO(
"%s", error.what());
126 catch(
const rs2::error & error)
128 UWARN(
"%s", error.what());
133 catch(
const rs2::error & error)
135 UWARN(
"%s", error.what());
137 delete depthIntrinsics_;
138 delete rgbIntrinsics_;
139 delete depthToRGBExtrinsics_;
143 #ifdef RTABMAP_REALSENSE2 144 void CameraRealSense2::imu_callback(rs2::frame frame)
146 auto stream = frame.get_profile().stream_type();
147 cv::Vec3f crnt_reading = *
reinterpret_cast<const cv::Vec3f*
>(frame.get_data());
148 UDEBUG(
"%s callback! %f (%f %f %f)",
149 stream == RS2_STREAM_GYRO?
"GYRO":
"ACC",
150 frame.get_timestamp(),
155 if(stream == RS2_STREAM_GYRO)
157 gyroBuffer_.insert(gyroBuffer_.end(), std::make_pair(frame.get_timestamp(), crnt_reading));
158 if(gyroBuffer_.size() > 1000)
160 gyroBuffer_.erase(gyroBuffer_.begin());
165 accBuffer_.insert(accBuffer_.end(), std::make_pair(frame.get_timestamp(), crnt_reading));
166 if(accBuffer_.size() > 1000)
168 accBuffer_.erase(accBuffer_.begin());
179 void CameraRealSense2::pose_callback(rs2::frame frame)
181 rs2_pose pose = frame.as<rs2::pose_frame>().get_pose_data();
192 UDEBUG(
"POSE callback! %f %s (confidence=%d)", frame.get_timestamp(), poseT.
prettyPrint().c_str(), (int)pose.tracker_confidence);
195 poseBuffer_.insert(poseBuffer_.end(), std::make_pair(frame.get_timestamp(), std::make_pair(poseT, pose.tracker_confidence)));
196 if(poseBuffer_.size() > 1000)
198 poseBuffer_.erase(poseBuffer_.begin());
202 void CameraRealSense2::frame_callback(rs2::frame frame)
204 UDEBUG(
"Frame callback! %f", frame.get_timestamp());
207 void CameraRealSense2::multiple_message_callback(rs2::frame frame)
209 auto stream = frame.get_profile().stream_type();
212 case RS2_STREAM_GYRO:
213 case RS2_STREAM_ACCEL:
217 case RS2_STREAM_POSE:
219 if(odometryProvided_)
221 pose_callback(frame);
226 frame_callback(frame);
230 void CameraRealSense2::getPoseAndIMU(
231 const double & stamp,
233 unsigned int & poseConfidence,
240 if(accBuffer_.empty() || gyroBuffer_.empty())
246 if(!poseBuffer_.empty())
250 while(maxWaitTimeMs>0 && poseBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
257 if(poseBuffer_.rbegin()->first < stamp)
259 if(maxWaitTimeMs > 0)
261 UWARN(
"Could not find poses to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, poseBuffer_.rbegin()->first);
266 std::map<double, std::pair<Transform, unsigned int> >::const_iterator iterB = poseBuffer_.lower_bound(stamp);
267 std::map<double, std::pair<Transform, unsigned int> >::const_iterator iterA = iterB;
268 if(iterA != poseBuffer_.begin())
272 if(iterB == poseBuffer_.end())
276 if(iterA == iterB && stamp == iterA->first)
278 pose = iterA->second.first;
279 poseConfidence = iterA->second.second;
281 else if(stamp >= iterA->first && stamp <= iterB->first)
283 pose = iterA->second.first.
interpolate((stamp-iterA->first) / (iterB->first-iterA->first), iterB->second.first);
284 poseConfidence = iterA->second.second;
286 else if(stamp < iterA->first)
288 UWARN(
"Could not find poses to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp, iterA->first);
292 UWARN(
"Could not find poses to interpolate at image time %f (between %f and %f), Are sensors synchronized?", stamp, iterA->first, iterB->first);
305 while(maxWaitTimeMs > 0 && accBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
313 if(globalTimeSync_ && accBuffer_.rbegin()->first < stamp)
317 UWARN(
"Could not find acc data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, accBuffer_.rbegin()->first);
324 std::map<double, cv::Vec3f>::const_iterator iterB = accBuffer_.lower_bound(stamp);
325 std::map<double, cv::Vec3f>::const_iterator iterA = iterB;
326 if(iterA != accBuffer_.begin())
330 if(iterB == accBuffer_.end())
334 if(iterA == iterB && stamp == iterA->first)
336 acc[0] = iterA->second[0];
337 acc[1] = iterA->second[1];
338 acc[2] = iterA->second[2];
340 else if(stamp >= iterA->first && stamp <= iterB->first)
342 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
343 acc[0] = iterA->second[0] + t*(iterB->second[0] - iterA->second[0]);
344 acc[1] = iterA->second[1] + t*(iterB->second[1] - iterA->second[1]);
345 acc[2] = iterA->second[2] + t*(iterB->second[2] - iterA->second[2]);
349 if(!imuGlobalSyncWarningShown_)
351 if(stamp < iterA->first)
353 UWARN(
"Could not find acc data to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp, iterA->first);
357 UWARN(
"Could not find acc data to interpolate at image time %f (between %f and %f). Are sensors synchronized?", stamp, iterA->first, iterB->first);
362 if(!imuGlobalSyncWarningShown_)
364 UWARN(
"As globalTimeSync option is off, the received gyro and accelerometer will be re-stamped with image time. This message is only shown once.");
365 imuGlobalSyncWarningShown_ =
true;
367 std::map<double, cv::Vec3f>::const_reverse_iterator iterC = accBuffer_.rbegin();
368 acc[0] = iterC->second[0];
369 acc[1] = iterC->second[1];
370 acc[2] = iterC->second[2];
389 while(maxWaitTimeMs>0 && gyroBuffer_.rbegin()->first < stamp && waitTry < maxWaitTimeMs)
397 if(globalTimeSync_ && gyroBuffer_.rbegin()->first < stamp)
401 UWARN(
"Could not find gyro data to interpolate at image time %f after waiting %d ms (last is %f)...", stamp, maxWaitTimeMs, gyroBuffer_.rbegin()->first);
408 std::map<double, cv::Vec3f>::const_iterator iterB = gyroBuffer_.lower_bound(stamp);
409 std::map<double, cv::Vec3f>::const_iterator iterA = iterB;
410 if(iterA != gyroBuffer_.begin())
414 if(iterB == gyroBuffer_.end())
418 if(iterA == iterB && stamp == iterA->first)
420 gyro[0] = iterA->second[0];
421 gyro[1] = iterA->second[1];
422 gyro[2] = iterA->second[2];
424 else if(stamp >= iterA->first && stamp <= iterB->first)
426 float t = (stamp-iterA->first) / (iterB->first-iterA->first);
427 gyro[0] = iterA->second[0] + t*(iterB->second[0] - iterA->second[0]);
428 gyro[1] = iterA->second[1] + t*(iterB->second[1] - iterA->second[1]);
429 gyro[2] = iterA->second[2] + t*(iterB->second[2] - iterA->second[2]);
433 if(!imuGlobalSyncWarningShown_)
435 if(stamp < iterA->first)
437 UWARN(
"Could not find gyro data to interpolate at image time %f (earliest is %f). Are sensors synchronized?", stamp, iterA->first);
441 UWARN(
"Could not find gyro data to interpolate at image time %f (between %f and %f). Are sensors synchronized?", stamp, iterA->first, iterB->first);
446 if(!imuGlobalSyncWarningShown_)
448 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.");
449 imuGlobalSyncWarningShown_ =
true;
451 std::map<double, cv::Vec3f>::const_reverse_iterator iterC = gyroBuffer_.rbegin();
452 gyro[0] = iterC->second[0];
453 gyro[1] = iterC->second[1];
454 gyro[2] = iterC->second[2];
466 imu =
IMU(gyro, cv::Mat::eye(3, 3, CV_64FC1), acc, cv::Mat::eye(3, 3, CV_64FC1), imuLocalTransform_);
473 #ifdef RTABMAP_REALSENSE2 475 UINFO(
"setupDevice...");
477 for(
size_t i=0; i<dev_.size(); ++i)
482 clockSyncWarningShown_ =
false;
483 imuGlobalSyncWarningShown_ =
false;
485 auto list = ctx_->query_devices();
486 if (0 == list.size())
488 UERROR(
"No RealSense2 devices were found!");
493 for (
auto&& dev : list)
495 auto sn = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
496 auto pid_str = dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID);
498 std::stringstream ss;
499 ss << std::hex << pid_str;
501 UINFO(
"Device with serial number %s was found with product ID=%d.", sn, (
int)pid);
502 if(dualMode_ && pid == 0x0B37)
509 else if (!found && (deviceId_.empty() || deviceId_ == sn))
519 if(dualMode_ && dev_[1]!=0)
521 UERROR(
"Dual setup is enabled, but a D400 camera is not detected!");
527 UERROR(
"The requested device \"%s\" is NOT found!", deviceId_.c_str());
531 else if(dualMode_ && dev_[1] == 0)
533 UERROR(
"Dual setup is enabled, but a T265 camera is not detected!");
539 if (!jsonConfig_.empty())
541 if (dev_[0]->is<rs400::advanced_mode>())
543 std::stringstream ss;
544 std::ifstream in(jsonConfig_);
548 std::string json_file_content = ss.str();
550 auto adv = dev_[0]->as<rs400::advanced_mode>();
551 adv.load_json(json_file_content);
552 UINFO(
"JSON file is loaded! (%s)", jsonConfig_.c_str());
556 UWARN(
"JSON file provided doesn't exist! (%s)", jsonConfig_.c_str());
561 UWARN(
"A json config file is provided (%s), but device does not support advanced settings!", jsonConfig_.c_str());
565 ctx_->set_devices_changed_callback([
this](rs2::event_information& info)
567 for(
size_t i=0; i<dev_.size(); ++i)
571 if (info.was_removed(*dev_[i]))
575 UDEBUG(
"The device %d has been disconnected!", i);
579 UERROR(
"The device %d has been disconnected!", i);
587 auto camera_name = dev_[0]->get_info(RS2_CAMERA_INFO_NAME);
588 UINFO(
"Device Name: %s", camera_name);
590 auto sn = dev_[0]->get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
591 UINFO(
"Device Serial No: %s", sn);
593 auto fw_ver = dev_[0]->get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);
594 UINFO(
"Device FW version: %s", fw_ver);
596 auto pid = dev_[0]->get_info(RS2_CAMERA_INFO_PRODUCT_ID);
597 UINFO(
"Device Product ID: 0x%s", pid);
599 auto dev_sensors = dev_[0]->query_sensors();
602 auto dev_sensors2 = dev_[1]->query_sensors();
603 dev_sensors.insert(dev_sensors.end(), dev_sensors2.begin(), dev_sensors2.end());
606 UINFO(
"Device Sensors: ");
607 std::vector<rs2::sensor> sensors(2);
610 for(
auto&& elem : dev_sensors)
612 std::string module_name = elem.get_info(RS2_CAMERA_INFO_NAME);
613 if (
"Stereo Module" == module_name)
616 sensors[1].set_option(rs2_option::RS2_OPTION_EMITTER_ENABLED, emitterEnabled_);
618 else if (
"Coded-Light Depth Sensor" == module_name)
621 else if (
"RGB Camera" == module_name)
628 else if (
"Wide FOV Camera" == module_name)
631 else if (
"Motion Module" == module_name)
639 else if (
"Tracking Module" == module_name)
650 sensors.back() = elem;
651 sensors.back().set_option(rs2_option::RS2_OPTION_ENABLE_POSE_JUMPING, 0);
652 sensors.back().set_option(rs2_option::RS2_OPTION_ENABLE_RELOCALIZATION, 0);
654 else if (
"L500 Depth Sensor" == module_name)
661 UERROR(
"Module Name \"%s\" isn't supported!", module_name.c_str());
664 UINFO(
"%s was found.", elem.get_info(RS2_CAMERA_INFO_NAME));
670 rs2::stream_profile depthStreamProfile;
671 rs2::stream_profile rgbStreamProfile;
672 std::vector<std::vector<rs2::stream_profile> > profilesPerSensor(sensors.size());
673 for (
unsigned int i=0; i<sensors.size(); ++i)
675 if(i==0 && ir_ && !stereo)
679 UINFO(
"Sensor %d \"%s\"", (
int)i, sensors[i].get_info(RS2_CAMERA_INFO_NAME));
680 auto profiles = sensors[i].get_stream_profiles();
682 UINFO(
"profiles=%d", (
int)profiles.size());
687 auto video_profile =
profile.as<rs2::video_stream_profile>();
688 UINFO(
"%s %d %d %d %d %s type=%d", rs2_format_to_string(
689 video_profile.format()),
690 video_profile.width(),
691 video_profile.height(),
693 video_profile.stream_index(),
694 video_profile.stream_name().c_str(),
695 video_profile.stream_type());
701 auto video_profile =
profile.as<rs2::video_stream_profile>();
705 (video_profile.width() == 640 &&
706 video_profile.height() == 480 &&
707 video_profile.fps() == 30))
710 && video_profile.format() == RS2_FORMAT_RGB8 && video_profile.stream_type() == RS2_STREAM_COLOR)
712 auto intrinsic = video_profile.get_intrinsics();
713 profilesPerSensor[i].push_back(
profile);
714 rgbBuffer_ = cv::Mat(cv::Size(video_profile.width(), video_profile.height()), CV_8UC3, cv::Scalar(0, 0, 0));
715 model_ =
CameraModel(camera_name, intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy, this->getLocalTransform(), 0, cv::Size(intrinsic.width, intrinsic.height));
717 *rgbIntrinsics_ = intrinsic;
721 && video_profile.format() == RS2_FORMAT_Z16 && video_profile.stream_type() == RS2_STREAM_DEPTH)
723 auto intrinsic = video_profile.get_intrinsics();
724 profilesPerSensor[i].push_back(
profile);
725 depthBuffer_ = cv::Mat(cv::Size(video_profile.width(), video_profile.height()), CV_16UC1, cv::Scalar(0));
727 *depthIntrinsics_ = intrinsic;
733 (video_profile.width() == cameraWidth_ &&
734 video_profile.height() == cameraHeight_ &&
735 video_profile.fps() == cameraFps_))
737 auto intrinsic = video_profile.get_intrinsics();
740 if((!ir_ && video_profile.format() == RS2_FORMAT_RGB8 && video_profile.stream_type() == RS2_STREAM_COLOR) ||
741 (ir_ && video_profile.format() == RS2_FORMAT_Y8 && video_profile.stream_index() == 1))
743 if(!profilesPerSensor[i].empty())
746 profilesPerSensor[i].push_back(profilesPerSensor[i].back());
747 profilesPerSensor[i].front() =
profile;
751 profilesPerSensor[i].push_back(
profile);
753 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));
754 model_ =
CameraModel(camera_name, intrinsic.fx, intrinsic.fy, intrinsic.ppx, intrinsic.ppy, this->getLocalTransform(), 0, cv::Size(intrinsic.width, intrinsic.height));
756 *rgbIntrinsics_ = intrinsic;
758 if(video_profile.format() == RS2_FORMAT_RGB8 || profilesPerSensor[i].size()==2)
764 else if(((!ir_ || irDepth_) && video_profile.format() == RS2_FORMAT_Z16) ||
765 (ir_ && !irDepth_ && video_profile.format() == RS2_FORMAT_Y8 && video_profile.stream_index() == 2))
767 profilesPerSensor[i].push_back(
profile);
768 depthBuffer_ = cv::Mat(cv::Size(cameraWidth_, cameraHeight_), video_profile.format() == RS2_FORMAT_Y8?CV_8UC1:CV_16UC1, cv::Scalar(0));
770 *depthIntrinsics_ = intrinsic;
772 if(!ir_ || irDepth_ || profilesPerSensor[i].size()==2)
778 else if(video_profile.format() == RS2_FORMAT_MOTION_XYZ32F || video_profile.format() == RS2_FORMAT_6DOF)
789 bool modified =
false;
790 for (
size_t j= 0; j < profilesPerSensor[i].size(); ++j)
792 if (profilesPerSensor[i][j].stream_type() ==
profile.stream_type())
794 if (
profile.stream_type() == RS2_STREAM_ACCEL)
796 if(
profile.fps() > profilesPerSensor[i][j].fps())
797 profilesPerSensor[i][j] =
profile;
800 else if (
profile.stream_type() == RS2_STREAM_GYRO)
802 if(
profile.fps() < profilesPerSensor[i][j].fps())
803 profilesPerSensor[i][j] =
profile;
809 profilesPerSensor[i].push_back(
profile);
813 else if(stereo || dualMode_)
817 video_profile.format() == RS2_FORMAT_Y8 &&
818 video_profile.width() == 848 &&
819 video_profile.height() == 800 &&
820 video_profile.fps() == 30)
823 profilesPerSensor[i].push_back(
profile);
824 auto intrinsic = video_profile.get_intrinsics();
828 rgbBuffer_ = cv::Mat(cv::Size(848, 800), CV_8UC1, cv::Scalar(0));
830 *rgbIntrinsics_ = intrinsic;
835 depthBuffer_ = cv::Mat(cv::Size(848, 800), CV_8UC1, cv::Scalar(0));
837 *depthIntrinsics_ = intrinsic;
841 else if(video_profile.format() == RS2_FORMAT_MOTION_XYZ32F || video_profile.format() == RS2_FORMAT_6DOF)
846 profilesPerSensor[i].push_back(
profile);
854 UERROR(
"Given stream configuration is not supported by the device! " 855 "Stream Index: %d, Width: %d, Height: %d, FPS: %d", i, cameraWidth_, cameraHeight_, cameraFps_);
856 UERROR(
"Available configurations:");
859 auto video_profile =
profile.as<rs2::video_stream_profile>();
860 UERROR(
"%s %d %d %d %d %s type=%d", rs2_format_to_string(
861 video_profile.format()),
862 video_profile.width(),
863 video_profile.height(),
865 video_profile.stream_index(),
866 video_profile.stream_name().c_str(),
867 video_profile.stream_type());
875 if(!model_.isValidForProjection())
877 UERROR(
"Calibration info not valid!");
880 *depthToRGBExtrinsics_ = depthStreamProfile.get_extrinsics_to(rgbStreamProfile);
884 Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
885 UINFO(
"Set base to pose");
887 UINFO(
"poseToLeftIR = %s", dualExtrinsics_.prettyPrint().c_str());
892 depthToRGBExtrinsics_->rotation[0], depthToRGBExtrinsics_->rotation[1], depthToRGBExtrinsics_->rotation[2], depthToRGBExtrinsics_->translation[0],
893 depthToRGBExtrinsics_->rotation[3], depthToRGBExtrinsics_->rotation[4], depthToRGBExtrinsics_->rotation[5], depthToRGBExtrinsics_->translation[1],
894 depthToRGBExtrinsics_->rotation[6], depthToRGBExtrinsics_->rotation[7], depthToRGBExtrinsics_->rotation[8], depthToRGBExtrinsics_->translation[2]);
895 leftIRToRGB = leftIRToRGB.
inverse();
897 baseToCam *= leftIRToRGB;
899 UASSERT(profilesPerSensor.size()>=2);
900 UASSERT(profilesPerSensor.back().size() == 3);
901 rs2_extrinsics poseToIMU = profilesPerSensor.back()[0].get_extrinsics_to(profilesPerSensor.back()[2]);
904 poseToIMU.rotation[0], poseToIMU.rotation[1], poseToIMU.rotation[2], poseToIMU.translation[0],
905 poseToIMU.rotation[3], poseToIMU.rotation[4], poseToIMU.rotation[5], poseToIMU.translation[1],
906 poseToIMU.rotation[6], poseToIMU.rotation[7], poseToIMU.rotation[8], poseToIMU.translation[2]);
907 poseToIMUT = realsense2PoseRotation_ * poseToIMUT;
908 UINFO(
"poseToIMU = %s", poseToIMUT.prettyPrint().c_str());
910 UINFO(
"BaseToCam = %s", baseToCam.prettyPrint().c_str());
911 model_.setLocalTransform(baseToCam);
915 if(ir_ && !irDepth_ && profilesPerSensor.size() >= 2 && profilesPerSensor[1].size() >= 2)
917 rs2_extrinsics leftToRight = profilesPerSensor[1][1].get_extrinsics_to(profilesPerSensor[1][0]);
919 leftToRight.rotation[0], leftToRight.rotation[1], leftToRight.rotation[2], leftToRight.translation[0],
920 leftToRight.rotation[3], leftToRight.rotation[4], leftToRight.rotation[5], leftToRight.translation[1],
921 leftToRight.rotation[6], leftToRight.rotation[7], leftToRight.rotation[8], leftToRight.translation[2]);
926 stereoModel_ =
StereoCameraModel(model_.fx(), model_.fy(), model_.cx(), model_.cy(), leftToRightT.
x(), model_.localTransform(), model_.imageSize());
927 UINFO(
"Stereo parameters: fx=%f cx=%f cy=%f baseline=%f",
928 stereoModel_.left().fx(),
929 stereoModel_.left().cx(),
930 stereoModel_.left().cy(),
931 stereoModel_.baseline());
934 if(!dualMode_ && profilesPerSensor.size() == 3)
936 if(!profilesPerSensor[2].empty() && !profilesPerSensor[0].empty())
938 rs2_extrinsics leftToIMU = profilesPerSensor[2][0].get_extrinsics_to(profilesPerSensor[0][0]);
940 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
941 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
942 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
944 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
946 else if(!profilesPerSensor[2].empty() && !profilesPerSensor[1].empty())
948 rs2_extrinsics leftToIMU = profilesPerSensor[2][0].get_extrinsics_to(profilesPerSensor[1][0]);
950 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
951 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
952 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
955 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
963 std::string serial = sn;
964 if(!cameraName.empty())
968 if(!calibrationFolder.empty() && !serial.empty())
970 if(!stereoModel_.load(calibrationFolder, serial,
false))
972 UWARN(
"Missing calibration files for camera \"%s\" in \"%s\" folder, you should calibrate the camera!",
973 serial.c_str(), calibrationFolder.c_str());
977 UINFO(
"Stereo parameters: fx=%f cx=%f cy=%f baseline=%f",
978 stereoModel_.left().fx(),
979 stereoModel_.left().cx(),
980 stereoModel_.left().cy(),
981 stereoModel_.baseline());
991 UASSERT(profilesPerSensor[0].size() == 5);
992 if(odometryProvided_)
994 rs2_extrinsics poseToLeft = profilesPerSensor[0][0].get_extrinsics_to(profilesPerSensor[0][4]);
995 rs2_extrinsics poseToIMU = profilesPerSensor[0][2].get_extrinsics_to(profilesPerSensor[0][4]);
997 poseToLeft.rotation[0], poseToLeft.rotation[1], poseToLeft.rotation[2], poseToLeft.translation[0],
998 poseToLeft.rotation[3], poseToLeft.rotation[4], poseToLeft.rotation[5], poseToLeft.translation[1],
999 poseToLeft.rotation[6], poseToLeft.rotation[7], poseToLeft.rotation[8], poseToLeft.translation[2]);
1000 poseToLeftT = realsense2PoseRotation_ * poseToLeftT;
1001 UINFO(
"poseToLeft = %s", poseToLeftT.prettyPrint().c_str());
1004 poseToIMU.rotation[0], poseToIMU.rotation[1], poseToIMU.rotation[2], poseToIMU.translation[0],
1005 poseToIMU.rotation[3], poseToIMU.rotation[4], poseToIMU.rotation[5], poseToIMU.translation[1],
1006 poseToIMU.rotation[6], poseToIMU.rotation[7], poseToIMU.rotation[8], poseToIMU.translation[2]);
1007 poseToIMUT = realsense2PoseRotation_ * poseToIMUT;
1008 UINFO(
"poseToIMU = %s", poseToIMUT.prettyPrint().c_str());
1010 UINFO(
"Set base to pose");
1011 Transform opticalTransform(0, 0, 1, 0, -1, 0, 0, 0, 0, -1, 0, 0);
1019 rs2_extrinsics leftToIMU = profilesPerSensor[0][2].get_extrinsics_to(profilesPerSensor[0][0]);
1021 leftToIMU.rotation[0], leftToIMU.rotation[1], leftToIMU.rotation[2], leftToIMU.translation[0],
1022 leftToIMU.rotation[3], leftToIMU.rotation[4], leftToIMU.rotation[5], leftToIMU.translation[1],
1023 leftToIMU.rotation[6], leftToIMU.rotation[7], leftToIMU.rotation[8], leftToIMU.translation[2]);
1026 UINFO(
"imu local transform = %s", imuLocalTransform_.prettyPrint().c_str());
1029 if(rectifyImages_ && !stereoModel_.isValidForRectification())
1031 UERROR(
"Parameter \"rectifyImages\" is set, but no stereo model is loaded or valid.");
1036 std::function<void(rs2::frame)> multiple_message_callback_function = [
this](rs2::frame frame){multiple_message_callback(frame);};
1038 for (
unsigned int i=0; i<sensors.size(); ++i)
1040 if(profilesPerSensor[i].size())
1042 UINFO(
"Starting sensor %d with %d profiles", (
int)i, (
int)profilesPerSensor[i].size());
1043 for (
size_t j = 0; j < profilesPerSensor[i].size(); ++j)
1045 auto video_profile = profilesPerSensor[i][j].as<rs2::video_stream_profile>();
1046 UINFO(
"Opening: %s %d %d %d %d %s type=%d", rs2_format_to_string(
1047 video_profile.format()),
1048 video_profile.width(),
1049 video_profile.height(),
1050 video_profile.fps(),
1051 video_profile.stream_index(),
1052 video_profile.stream_name().c_str(),
1053 video_profile.stream_type());
1055 if(globalTimeSync_ && sensors[i].supports(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED))
1057 float value = sensors[i].get_option(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED);
1058 UINFO(
"Set RS2_OPTION_GLOBAL_TIME_ENABLED=1 (was %f) for sensor %d", value, (
int)i);
1059 sensors[i].set_option(rs2_option::RS2_OPTION_GLOBAL_TIME_ENABLED, 1);
1061 sensors[i].open(profilesPerSensor[i]);
1062 if(sensors[i].is<rs2::depth_sensor>())
1064 auto depth_sensor = sensors[i].as<rs2::depth_sensor>();
1065 depth_scale_meters_ = depth_sensor.get_depth_scale();
1066 UINFO(
"Depth scale %f for sensor %d", depth_scale_meters_, (
int)i);
1068 sensors[i].start(multiple_message_callback_function);
1073 UINFO(
"Enabling streams...done!");
1078 UERROR(
"CameraRealSense: RTAB-Map is not built with RealSense2 support!");
1085 #ifdef RTABMAP_REALSENSE2 1086 return model_.isValidForProjection() || stereoModel_.isValidForRectification();
1094 #ifdef RTABMAP_REALSENSE2 1097 return dev_[0]->get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
1105 #ifdef RTABMAP_REALSENSE2 1106 return odometryProvided_;
1114 #ifdef RTABMAP_REALSENSE2 1115 emitterEnabled_ = enabled;
1121 #ifdef RTABMAP_REALSENSE2 1123 irDepth_ = useDepthInsteadOfRightImage;
1129 #ifdef RTABMAP_REALSENSE2 1130 cameraWidth_ = width;
1131 cameraHeight_ = height;
1138 #ifdef RTABMAP_REALSENSE2 1139 globalTimeSync_ = enabled;
1145 #ifdef RTABMAP_REALSENSE2 1146 publishInterIMU_ = enabled;
1152 #ifdef RTABMAP_REALSENSE2 1154 dualMode_ = enabled;
1155 dualExtrinsics_ = extrinsics;
1158 odometryProvided_ =
true;
1165 #ifdef RTABMAP_REALSENSE2 1172 #ifdef RTABMAP_REALSENSE2 1173 rectifyImages_ = enabled;
1179 #ifdef RTABMAP_REALSENSE2 1180 if(dualMode_ && !enabled)
1182 UERROR(
"Odometry is disabled but dual mode was enabled, disabling dual mode.");
1185 odometryProvided_ = enabled;
1192 #ifdef RTABMAP_REALSENSE2 1195 auto frameset = syncer_->wait_for_frames(5000);
1197 int desiredFramesetSize = 2;
1198 if(isL500_ && globalTimeSync_)
1199 desiredFramesetSize = 3;
1200 while ((
int)frameset.size() != desiredFramesetSize && timer.
elapsed() < 2.0)
1203 frameset = syncer_->wait_for_frames(100);
1205 if ((
int)frameset.size() == desiredFramesetSize)
1208 bool is_rgb_arrived =
false;
1209 bool is_depth_arrived =
false;
1210 bool is_left_fisheye_arrived =
false;
1211 bool is_right_fisheye_arrived =
false;
1212 rs2::frame rgb_frame;
1213 rs2::frame depth_frame;
1214 double stamp = frameset.get_timestamp();
1215 for (
auto it = frameset.begin(); it != frameset.end(); ++it)
1218 if(stamp >
f.get_timestamp())
1220 stamp =
f.get_timestamp();
1222 auto stream_type =
f.get_profile().stream_type();
1223 if (stream_type == RS2_STREAM_COLOR || stream_type == RS2_STREAM_INFRARED)
1227 if(stream_type == RS2_STREAM_COLOR)
1230 is_rgb_arrived =
true;
1233 else if(ir_ && !irDepth_)
1236 if(!is_depth_arrived)
1239 is_depth_arrived =
true;
1244 is_rgb_arrived =
true;
1250 is_rgb_arrived =
true;
1253 else if (stream_type == RS2_STREAM_DEPTH)
1256 is_depth_arrived =
true;
1258 else if (stream_type == RS2_STREAM_FISHEYE)
1260 if(!is_right_fisheye_arrived)
1263 is_right_fisheye_arrived =
true;
1268 is_left_fisheye_arrived =
true;
1274 UDEBUG(
"Frameset arrived. system=%fs frame=%fs", now, stamp);
1275 if(stamp - now > 1000000000.0)
1277 if(!clockSyncWarningShown_)
1279 UWARN(
"Clocks are not sync with host computer! Detected stamps in far " 1280 "future %f, thus using host time instead (%f)! This message " 1281 "will only appear once. " 1282 "See https://github.com/IntelRealSense/librealsense/issues/4505 " 1283 "for more info", stamp, now);
1284 clockSyncWarningShown_ =
true;
1289 if(is_rgb_arrived && is_depth_arrived)
1294 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()).clone();
1298 rs2::align align(rgb_frame.get_profile().stream_type());
1299 rs2::frameset processed = frameset.apply_filter(align);
1300 rs2::depth_frame aligned_depth_frame = processed.get_depth_frame();
1301 depth = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)aligned_depth_frame.get_data()).clone();
1302 if(depth_scale_meters_ != 0.001
f)
1304 if(depth.type() == CV_16UC1)
1306 float scale = depth_scale_meters_ / 0.001f;
1308 int buffSize = depth.rows * depth.cols;
1309 #pragma omp parallel for 1310 for(
int i = 0; i < buffSize; ++i) {
1317 cv::Mat rgb = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data());
1319 if(rgb.channels() == 3)
1321 cv::cvtColor(rgb, bgr, CV_RGB2BGR);
1328 if(ir_ && !irDepth_)
1338 else if(is_left_fisheye_arrived && is_right_fisheye_arrived)
1340 auto from_image_frame = depth_frame.as<rs2::video_frame>();
1342 if(rectifyImages_ && stereoModel_.left().isValidForRectification() && stereoModel_.right().isValidForRectification())
1344 left = stereoModel_.left().rectifyImage(cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()));
1345 right = stereoModel_.right().rectifyImage(cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()));
1349 left = cv::Mat(rgbBuffer_.size(), rgbBuffer_.type(), (
void*)rgb_frame.get_data()).clone();
1350 right = cv::Mat(depthBuffer_.size(), depthBuffer_.type(), (
void*)depth_frame.get_data()).clone();
1353 if(stereoModel_.left().imageHeight() == 0 || stereoModel_.left().imageWidth() == 0)
1355 stereoModel_.setImageSize(left.size());
1362 UERROR(
"Not received depth and rgb");
1366 unsigned int confidence = 0;
1367 double imuStamp = stamp*1000.0;
1369 getPoseAndIMU(imuStamp, pose, confidence, imu);
1371 if(info && odometryProvided_ && !pose.
isNull())
1380 if(!imu.
empty() && !publishInterIMU_)
1384 else if(publishInterIMU_ && !gyroBuffer_.empty())
1386 if(lastImuStamp_ > 0.0)
1388 UASSERT(imuStamp > lastImuStamp_);
1390 std::map<double, cv::Vec3f>::iterator iterA = gyroBuffer_.upper_bound(lastImuStamp_);
1391 std::map<double, cv::Vec3f>::iterator iterB = gyroBuffer_.lower_bound(imuStamp);
1392 if(iterA != gyroBuffer_.end())
1396 if(iterB != gyroBuffer_.end())
1403 for(;iterA != iterB;++iterA)
1407 getPoseAndIMU(iterA->first, tmp, confidence, imuTmp);
1418 UDEBUG(
"inter imu published=%d, %f -> %f", pub, lastImuStamp_, imuStamp);
1422 lastImuStamp_ = imuStamp;
1425 else if(isL500_ && globalTimeSync_)
1427 UERROR(
"Missing frames (received %d, needed=%d). L500 camera is used and global time sync is enabled, try disabling global time sync for the RealSense2 driver.", (
int)frameset.size(), desiredFramesetSize);
1431 UERROR(
"Missing frames (received %d, needed=%d)", (
int)frameset.size(), desiredFramesetSize);
1434 catch(
const std::exception& ex)
1436 UERROR(
"An error has occurred during frame callback: %s", ex.what());
1439 UERROR(
"CameraRealSense2: RTAB-Map is not built with RealSense2 support!");
static void post(UEvent *event, bool async=true, const UEventsSender *sender=0)
void setDualMode(bool enabled, const Transform &extrinsics)
const Transform & getLocalTransform() const
void setJsonConfig(const std::string &json)
CameraRealSense2(const std::string &deviceId="", float imageRate=0, const Transform &localTransform=CameraModel::opticalRotation())
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)
virtual bool isCalibrated() const
Some conversion functions.
void publishInterIMU(bool enabled)
#define UASSERT(condition)
void setOdomProvided(bool enabled)
virtual std::string getSerial() const
GLM_FUNC_DECL genType pi()
static ULogger::Level level()
virtual ~CameraRealSense2()
bool odomProvided() const
void uSleep(unsigned int ms)
void setIRFormat(bool enabled, bool useDepthInsteadOfRightImage)
GLM_FUNC_DECL genType pow(genType const &base, genType const &exponent)
void setLocalTransform(const Transform &localTransform)
void setIMU(const IMU &imu)
void setResolution(int width, int height, int fps=30)
void setGlobalTimeSync(bool enabled)