30 #include <opencv2/highgui/highgui.hpp> 66 Eigen::Affine3d eigenTf;
78 long double recipNorm = 1.0 /
sqrt(msg.rotation.x * msg.rotation.x + msg.rotation.y * msg.rotation.y + msg.rotation.z * msg.rotation.z + msg.rotation.w * msg.rotation.w);
79 msg.rotation.x *= recipNorm;
80 msg.rotation.y *= recipNorm;
81 msg.rotation.z *= recipNorm;
82 msg.rotation.w *= recipNorm;
86 msg = geometry_msgs::Transform();
93 if(msg.rotation.w == 0 &&
94 msg.rotation.x == 0 &&
95 msg.rotation.y == 0 &&
101 Eigen::Affine3d tfTransform;
114 msg = geometry_msgs::Pose();
120 if(msg.orientation.w == 0 &&
121 msg.orientation.x == 0 &&
122 msg.orientation.y == 0 &&
123 msg.orientation.z == 0)
125 if(ignoreRotationIfNotSet)
131 Eigen::Affine3d tfPose;
138 if(!image.rgb.data.empty())
142 else if(!image.rgb_compressed.data.empty())
144 #ifdef CV_BRIDGE_HYDRO 145 ROS_ERROR(
"Unsupported compressed image copy, please upgrade at least to ROS Indigo to use this.");
151 if(!image.depth.data.empty())
155 else if(!image.depth_compressed.data.empty())
158 ptr->header = image.depth_compressed.header;
160 ROS_ASSERT(ptr->image.empty() || ptr->image.type() == CV_32FC1 || ptr->image.type() == CV_16UC1);
173 if(!image.rgb.data.empty())
177 else if(!image.rgb_compressed.data.empty())
179 #ifdef CV_BRIDGE_HYDRO 180 ROS_ERROR(
"Unsupported compressed image copy, please upgrade at least to ROS Indigo to use this.");
186 if(!image.depth.data.empty())
190 else if(!image.depth_compressed.data.empty())
192 if(image.depth_compressed.format.compare(
"jpg")==0)
194 #ifdef CV_BRIDGE_HYDRO 195 ROS_ERROR(
"Unsupported compressed image copy, please upgrade at least to ROS Indigo to use this.");
203 ptr->header = image.depth_compressed.header;
205 ROS_ASSERT(ptr->image.empty() || ptr->image.type() == CV_32FC1 || ptr->image.type() == CV_16UC1);
215 header.frame_id = sensorFrameId;
220 UERROR(
"Cannot convert multi-camera data to rgbd image");
227 msg.rgb_camera_info.header = header;
228 localTransform = data.
cameraModels().front().localTransform();
235 msg.rgb_camera_info.header = header;
236 msg.depth_camera_info.header = header;
251 ROS_ERROR(
"Conversion of compressed SensorData to RGBDImage is not implemented...");
265 ROS_ERROR(
"Conversion of compressed SensorData to RGBDImage is not implemented...");
284 msg.global_descriptor.header = header;
312 ROS_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8 (mono8 recommended), received types are %s (left) and %s (right)",
313 imageRectLeft->encoding.c_str(), imageRectRight->encoding.c_str());
317 if(!imageRectLeft->image.empty() && !imageRectRight->image.empty())
321 static bool shown =
false;
324 ROS_WARN(
"Detected baseline (%f m) is quite large! Is your " 325 "right camera_info P(0,3) correctly set? Note that " 326 "baseline=-P(0,3)/P(0,0). This warning is printed only once.",
336 left = imageRectLeft->image;
349 right = imageRectRight->image;
367 ROS_WARN(
"Odom: input images empty?!?");
373 int imageWidth = imageMsg->image.cols;
374 int imageHeight = imageMsg->image.rows;
375 int depthWidth = depthMsg->image.cols;
376 int depthHeight = depthMsg->image.rows;
379 imageWidth/depthWidth == imageHeight/depthHeight,
380 uFormat(
"rgb=%dx%d depth=%dx%d", imageWidth, imageHeight, depthWidth, depthHeight).c_str());
398 ROS_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8,bgra8,rgba8 and " 399 "image_depth=32FC1,16UC1,mono16. Current rgb=%s and depth=%s",
400 imageMsg->encoding.c_str(),
401 depthMsg->encoding.c_str());
435 UASSERT(compressed.empty() || compressed.type() == CV_8UC1);
437 if(!compressed.empty())
439 bytes.resize(compressed.cols * compressed.rows);
440 memcpy(bytes.data(), compressed.data, bytes.size());
449 out = cv::Mat(1, bytes.size(), CV_8UC1, (
void*)bytes.data());
466 stat.
setStamp(info.header.stamp.toSec());
474 std::map<int, float> mapIntFloat;
475 for(
unsigned int i=0; i<info.posteriorKeys.size() && i<info.posteriorValues.size(); ++i)
477 mapIntFloat.insert(std::pair<int, float>(info.posteriorKeys.at(i), info.posteriorValues.at(i)));
482 for(
unsigned int i=0; i<info.likelihoodKeys.size() && i<info.likelihoodValues.size(); ++i)
484 mapIntFloat.insert(std::pair<int, float>(info.likelihoodKeys.at(i), info.likelihoodValues.at(i)));
489 for(
unsigned int i=0; i<info.rawLikelihoodKeys.size() && i<info.rawLikelihoodValues.size(); ++i)
491 mapIntFloat.insert(std::pair<int, float>(info.rawLikelihoodKeys.at(i), info.rawLikelihoodValues.at(i)));
495 std::map<int, int> mapIntInt;
496 for(
unsigned int i=0; i<info.weightsKeys.size() && i<info.weightsValues.size(); ++i)
498 mapIntInt.insert(std::pair<int, int>(info.weightsKeys.at(i), info.weightsValues.at(i)));
502 std::map<int, std::string> mapIntStr;
503 for(
unsigned int i=0; i<info.labelsKeys.size() && i<info.labelsValues.size(); ++i)
505 mapIntStr.insert(std::pair<int, std::string>(info.labelsKeys.at(i), info.labelsValues.at(i)));
512 std::map<int, rtabmap::Transform> poses;
513 std::multimap<int, rtabmap::Link> constraints;
520 for(
unsigned int i=0; i<info.statsKeys.size() && i<info.statsValues.size(); i++)
522 stat.
addStatistic(info.statsKeys.at(i), info.statsValues.at(i));
531 info.landmarkId =
static_cast<int>(
uValue(stats.
data(), rtabmap::Statistics::kLoopLandmark_detected(), 0.0f));
539 info.wmState = stats.
wmState();
564 cv::Mat information = cv::Mat(6,6,CV_64FC1, (
void*)msg.information.data()).clone();
570 msg.fromId = link.
from();
571 msg.toId = link.
to();
572 msg.type = link.
type();
575 memcpy(msg.information.data(), link.
infMatrix().data, 36*
sizeof(double));
582 return cv::KeyPoint(msg.pt.x, msg.pt.y, msg.size, msg.angle, msg.response, msg.octave, msg.class_id);
587 msg.angle = kpt.angle;
588 msg.class_id = kpt.class_id;
589 msg.octave = kpt.octave;
592 msg.response = kpt.response;
598 std::vector<cv::KeyPoint> v(msg.size());
599 for(
unsigned int i=0; i<msg.size(); ++i)
606 void keypointsFromROS(
const std::vector<rtabmap_ros::KeyPoint> & msg, std::vector<cv::KeyPoint> & kpts,
int xShift)
608 size_t outCurrentIndex = kpts.size();
609 kpts.resize(kpts.size()+msg.size());
610 for(
unsigned int i=0; i<msg.size(); ++i)
613 kpts[outCurrentIndex+i].pt.x += xShift;
617 void keypointsToROS(
const std::vector<cv::KeyPoint> & kpts, std::vector<rtabmap_ros::KeyPoint> & msg)
619 msg.resize(kpts.size());
620 for(
unsigned int i=0; i<msg.size(); ++i)
633 msg.type = desc.
type();
642 std::vector<rtabmap::GlobalDescriptor> v(msg.size());
643 for(
unsigned int i=0; i<msg.size(); ++i)
649 return std::vector<rtabmap::GlobalDescriptor>();
652 void globalDescriptorsToROS(
const std::vector<rtabmap::GlobalDescriptor> & desc, std::vector<rtabmap_ros::GlobalDescriptor> & msg)
657 msg.resize(desc.size());
658 for(
unsigned int i=0; i<msg.size(); ++i)
672 msg.type = sensor.
type();
673 msg.value = sensor.
value();
682 for(
unsigned int i=0; i<msg.size(); ++i)
696 msg.resize(sensors.size());
698 for(rtabmap::EnvSensors::const_iterator iter=sensors.begin(); iter!=sensors.end(); ++iter)
707 return cv::Point2f(msg.x, msg.y);
716 std::vector<cv::Point2f>
points2fFromROS(
const std::vector<rtabmap_ros::Point2f> & msg)
718 std::vector<cv::Point2f> v(msg.size());
719 for(
unsigned int i=0; i<msg.size(); ++i)
726 void points2fToROS(
const std::vector<cv::Point2f> & kpts, std::vector<rtabmap_ros::Point2f> & msg)
728 msg.resize(kpts.size());
729 for(
unsigned int i=0; i<msg.size(); ++i)
737 return cv::Point3f(msg.x, msg.y, msg.z);
750 std::vector<cv::Point3f> v(msg.size());
751 for(
unsigned int i=0; i<msg.size(); ++i)
765 points3.resize(points3.size()+msg.size());
767 for(
unsigned int i=0; i<msg.size(); ++i)
779 msg.resize(pts.size());
781 for(
unsigned int i=0; i<msg.size(); ++i)
796 const sensor_msgs::CameraInfo & camInfo,
800 UASSERT(camInfo.K.empty() || camInfo.K.size() == 9);
801 if(!camInfo.K.empty())
803 K = cv::Mat(3, 3, CV_64FC1);
804 memcpy(K.data, camInfo.K.elems, 9*
sizeof(
double));
810 if(camInfo.D.size()>=4 &&
812 uStrContains(camInfo.distortion_model,
"equidistant") ||
813 uStrContains(camInfo.distortion_model,
"Kannala Brandt4")))
815 D = cv::Mat::zeros(1, 6, CV_64FC1);
816 D.at<
double>(0,0) = camInfo.D[0];
817 D.at<
double>(0,1) = camInfo.D[1];
818 D.at<
double>(0,4) = camInfo.D[2];
819 D.at<
double>(0,5) = camInfo.D[3];
821 else if(camInfo.D.size()>8)
823 bool zerosAfter8 =
true;
824 for(
size_t i=8; i<camInfo.D.size() && zerosAfter8; ++i)
826 if(camInfo.D[i] != 0.0)
831 static bool warned =
false;
832 if(!zerosAfter8 && !warned)
834 ROS_WARN(
"Camera info conversion: Distortion model is larger than 8, coefficients after 8 are ignored. This message is only shown once.");
837 D = cv::Mat(1, 8, CV_64FC1);
838 memcpy(D.data, camInfo.D.data(), D.cols*
sizeof(double));
842 D = cv::Mat(1, camInfo.D.size(), CV_64FC1);
843 memcpy(D.data, camInfo.D.data(), D.cols*
sizeof(double));
848 UASSERT(camInfo.R.empty() || camInfo.R.size() == 9);
849 if(!camInfo.R.empty())
851 R = cv::Mat(3, 3, CV_64FC1);
852 memcpy(R.data, camInfo.R.elems, 9*
sizeof(
double));
856 UASSERT(camInfo.P.empty() || camInfo.P.size() == 12);
857 if(!camInfo.P.empty())
859 P = cv::Mat(3, 4, CV_64FC1);
860 memcpy(P.data, camInfo.P.elems, 12*
sizeof(
double));
865 cv::Size(camInfo.width, camInfo.height),
871 sensor_msgs::CameraInfo & camInfo)
874 if(model.
K_raw().empty())
876 memset(camInfo.K.elems, 0.0, 9*
sizeof(
double));
880 memcpy(camInfo.K.elems, model.
K_raw().data, 9*
sizeof(double));
883 if(model.
D_raw().total() == 6)
885 camInfo.D = std::vector<double>(4);
886 camInfo.D[0] = model.
D_raw().at<
double>(0,0);
887 camInfo.D[1] = model.
D_raw().at<
double>(0,1);
888 camInfo.D[2] = model.
D_raw().at<
double>(0,4);
889 camInfo.D[3] = model.
D_raw().at<
double>(0,5);
890 camInfo.distortion_model =
"equidistant";
894 camInfo.D = std::vector<double>(model.
D_raw().cols);
895 memcpy(camInfo.D.data(), model.
D_raw().data, model.
D_raw().cols*
sizeof(double));
896 if(camInfo.D.size() > 5)
898 camInfo.distortion_model =
"rational_polynomial";
902 camInfo.distortion_model =
"plumb_bob";
906 UASSERT(model.
R().empty() || model.
R().total() == 9);
907 if(model.
R().empty())
909 memset(camInfo.R.elems, 0.0, 9*
sizeof(
double));
913 memcpy(camInfo.R.elems, model.
R().data, 9*
sizeof(double));
916 UASSERT(model.
P().empty() || model.
P().total() == 12);
917 if(model.
P().empty())
919 memset(camInfo.P.elems, 0.0, 12*
sizeof(
double));
923 memcpy(camInfo.P.elems, model.
P().data, 12*
sizeof(double));
926 camInfo.binning_x = 1;
927 camInfo.binning_y = 1;
935 const sensor_msgs::CameraInfo & leftCamInfo,
936 const sensor_msgs::CameraInfo & rightCamInfo,
947 const sensor_msgs::CameraInfo & leftCamInfo,
948 const sensor_msgs::CameraInfo & rightCamInfo,
951 double waitForTransform)
955 leftCamInfo.header.frame_id,
956 leftCamInfo.header.stamp,
959 if(localTransform.
isNull())
965 leftCamInfo.header.frame_id,
966 rightCamInfo.header.frame_id,
967 leftCamInfo.header.stamp,
970 if(stereoTransform.
isNull())
978 const rtabmap_ros::MapData & msg,
979 std::map<int, rtabmap::Transform> & poses,
980 std::multimap<int, rtabmap::Link> & links,
981 std::map<int, rtabmap::Signature> & signatures,
988 for(
unsigned int i=0; i<msg.nodes.size(); ++i)
990 signatures.insert(std::make_pair(msg.nodes[i].id,
nodeDataFromROS(msg.nodes[i])));
994 const std::map<int, rtabmap::Transform> & poses,
995 const std::multimap<int, rtabmap::Link> & links,
996 const std::map<int, rtabmap::Signature> & signatures,
998 rtabmap_ros::MapData & msg)
1004 msg.nodes.resize(signatures.size());
1006 for(std::multimap<int, rtabmap::Signature>::const_iterator iter = signatures.begin();
1007 iter!=signatures.end();
1015 const rtabmap_ros::MapGraph & msg,
1016 std::map<int, rtabmap::Transform> & poses,
1017 std::multimap<int, rtabmap::Link> & links,
1021 UASSERT(msg.posesId.size() == msg.poses.size());
1022 for(
unsigned int i=0; i<msg.posesId.size(); ++i)
1026 for(
unsigned int i=0; i<msg.links.size(); ++i)
1029 links.insert(std::make_pair(msg.links[i].fromId,
linkFromROS(msg.links[i])));
1034 const std::map<int, rtabmap::Transform> & poses,
1035 const std::multimap<int, rtabmap::Link> & links,
1037 rtabmap_ros::MapGraph & msg)
1040 msg.posesId.resize(poses.size());
1041 msg.poses.resize(poses.size());
1043 for(std::map<int, rtabmap::Transform>::const_iterator iter = poses.begin();
1044 iter != poses.end();
1047 msg.posesId[index] = iter->first;
1052 msg.links.resize(links.size());
1054 for(std::multimap<int, rtabmap::Link>::const_iterator iter = links.begin();
1058 linkToROS(iter->second, msg.links[index++]);
1067 std::multimap<int, int> words;
1068 std::vector<cv::KeyPoint> wordsKpts;
1069 std::vector<cv::Point3f> words3D;
1072 if(msg.wordIdKeys.size() != msg.wordIdValues.size())
1074 ROS_ERROR(
"Word ID keys and values should be the same size (%d, %d)!", (
int)msg.wordIdKeys.size(), (int)msg.wordIdValues.size());
1076 if(!msg.wordKpts.empty() && msg.wordKpts.size() != msg.wordIdKeys.size())
1078 ROS_ERROR(
"Word IDs and 2D keypoints should be the same size (%d, %d)!", (
int)msg.wordIdKeys.size(), (int)msg.wordKpts.size());
1080 if(!msg.wordPts.empty() && msg.wordPts.size() != msg.wordIdKeys.size())
1082 ROS_ERROR(
"Word IDs and 3D points should be the same size (%d, %d)!", (
int)msg.wordIdKeys.size(), (int)msg.wordPts.size());
1084 if(!wordsDescriptors.empty() && wordsDescriptors.rows != (int)msg.wordIdKeys.size())
1086 ROS_ERROR(
"Word IDs and descriptors should be the same size (%d, %d)!", (
int)msg.wordIdKeys.size(), wordsDescriptors.rows);
1087 wordsDescriptors = cv::Mat();
1090 if(msg.wordIdKeys.size() == msg.wordIdValues.size())
1092 for(
unsigned int i=0; i<msg.wordIdKeys.size(); ++i)
1094 words.insert(std::make_pair(msg.wordIdKeys.at(i), msg.wordIdValues.at(i)));
1095 if(msg.wordIdKeys.size() == msg.wordKpts.size())
1097 if(wordsKpts.empty())
1099 wordsKpts.reserve(msg.wordKpts.size());
1103 if(msg.wordIdKeys.size() == msg.wordPts.size())
1107 words3D.reserve(msg.wordPts.size());
1114 std::vector<rtabmap::StereoCameraModel> stereoModels;
1115 std::vector<rtabmap::CameraModel> models;
1116 if(msg.baseline.size())
1119 if(msg.fx.size() == msg.baseline.size() &&
1120 msg.fy.size() == msg.baseline.size() &&
1121 msg.cx.size() == msg.baseline.size() &&
1122 msg.cy.size() == msg.baseline.size() &&
1123 msg.width.size() == msg.baseline.size() &&
1124 msg.height.size() == msg.baseline.size() &&
1125 msg.localTransform.size() == msg.baseline.size())
1127 for(
unsigned int i=0; i<msg.fx.size(); ++i)
1136 cv::Size(msg.width[i], msg.height[i])));
1144 msg.fx.size() == msg.fy.size() &&
1145 msg.fx.size() == msg.cx.size() &&
1146 msg.fx.size() == msg.cy.size() &&
1147 msg.fx.size() == msg.localTransform.size())
1149 for(
unsigned int i=0; i<msg.fx.size(); ++i)
1164 cv::Size(msg.width[i], msg.height[i])));
1178 stereoModels.
size()?
1181 msg.laserScanMaxPts,
1182 msg.laserScanMaxRange,
1193 msg.laserScanMaxPts,
1194 msg.laserScanMaxRange,
1203 s.setWords(words, wordsKpts, words3D, wordsDescriptors);
1206 s.sensorData().setOccupancyGrid(
1212 s.sensorData().setGPS(
rtabmap::GPS(msg.gps.stamp, msg.gps.longitude, msg.gps.latitude, msg.gps.altitude, msg.gps.error, msg.gps.bearing));
1218 msg.id = signature.
id();
1219 msg.mapId = signature.
mapId();
1291 ROS_ERROR(
"Word IDs and 2D keypoints must have the same size (%d vs %d)!",
1299 ROS_ERROR(
"Word IDs and 3D points must have the same size (%d vs %d)!",
1304 msg.wordIdKeys.resize(signature.
getWords().size());
1305 msg.wordIdValues.resize(signature.
getWords().size());
1306 for(std::multimap<int, int>::const_iterator iter=signature.
getWords().begin();
1310 msg.wordIdKeys.at(i) = iter->first;
1311 msg.wordIdValues.at(i) = iter->second;
1314 if(msg.wordKpts.empty())
1316 msg.wordKpts.resize(signature.
getWords().size());
1322 if(msg.wordPts.empty())
1324 msg.wordPts.resize(signature.
getWords().size());
1339 ROS_ERROR(
"Word IDs and descriptors must have the same size (%d vs %d)!",
1364 msg.id = signature.
id();
1365 msg.mapId = signature.
mapId();
1375 std::map<std::string, float> stats;
1377 stats.insert(std::make_pair(
"Odometry/TimeRegistration/ms", info.
reg.
totalTime*1000.0f));
1378 stats.insert(std::make_pair(
"Odometry/RAM_usage/MB", info.
memoryUsage));
1381 stats.insert(std::make_pair(
"Odometry/Features/", info.
features));
1382 stats.insert(std::make_pair(
"Odometry/Matches/", info.
reg.
matches));
1384 stats.insert(std::make_pair(
"Odometry/Inliers/", info.
reg.
inliers));
1387 stats.insert(std::make_pair(
"Odometry/InliersRatio/", info.
reg.
inliers));
1389 stats.insert(std::make_pair(
"Odometry/ICPRotation/rad", info.
reg.
icpRotation));
1390 stats.insert(std::make_pair(
"Odometry/ICPTranslation/m", info.
reg.
icpTranslation));
1394 stats.insert(std::make_pair(
"Odometry/StdDevLin/",
sqrt((
float)info.
reg.
covariance.at<
double>(0,0))));
1395 stats.insert(std::make_pair(
"Odometry/StdDevAng/",
sqrt((
float)info.
reg.
covariance.at<
double>(5,5))));
1396 stats.insert(std::make_pair(
"Odometry/VarianceLin/", (
float)info.
reg.
covariance.at<
double>(0,0)));
1397 stats.insert(std::make_pair(
"Odometry/VarianceAng/", (
float)info.
reg.
covariance.at<
double>(5,5)));
1398 stats.insert(std::make_pair(
"Odometry/TimeEstimation/ms", info.
timeEstimation*1000.0f));
1400 stats.insert(std::make_pair(
"Odometry/LocalMapSize/", info.
localMapSize));
1401 stats.insert(std::make_pair(
"Odometry/LocalScanMapSize/", info.
localScanMapSize));
1402 stats.insert(std::make_pair(
"Odometry/LocalKeyFrames/", info.
localKeyFrames));
1405 stats.insert(std::make_pair(
"Odometry/LocalBundleTime/ms", info.
localBundleTime*1000.0f));
1406 stats.insert(std::make_pair(
"Odometry/KeyFrameAdded/", info.
keyFrameAdded?1.0f:0.0f));
1407 stats.insert(std::make_pair(
"Odometry/Interval/ms", (
float)info.
interval));
1411 float dist = 0.0f, speed=0.0f;
1416 stats.insert(std::make_pair(
"Odometry/T/m", dist));
1417 stats.insert(std::make_pair(
"Odometry/Tx/m", x));
1418 stats.insert(std::make_pair(
"Odometry/Ty/m", y));
1419 stats.insert(std::make_pair(
"Odometry/Tz/m", z));
1420 stats.insert(std::make_pair(
"Odometry/Troll/deg", roll*180.0/CV_PI));
1421 stats.insert(std::make_pair(
"Odometry/Tpitch/deg", pitch*180.0/CV_PI));
1422 stats.insert(std::make_pair(
"Odometry/Tyaw/deg", yaw*180.0/CV_PI));
1427 stats.insert(std::make_pair(
"Odometry/Speed/kph", speed*3.6));
1428 stats.insert(std::make_pair(
"Odometry/Speed/mph", speed*2.237));
1429 stats.insert(std::make_pair(
"Odometry/Speed/mps", speed));
1437 stats.insert(std::make_pair(
"Odometry/TG_error_lin/m", diff.
getNorm()));
1438 stats.insert(std::make_pair(
"Odometry/TG_error_ang/deg", diff.
getAngle()*180.0/CV_PI));
1443 stats.insert(std::make_pair(
"Odometry/TG/m", dist));
1444 stats.insert(std::make_pair(
"Odometry/TGx/m", x));
1445 stats.insert(std::make_pair(
"Odometry/TGy/m", y));
1446 stats.insert(std::make_pair(
"Odometry/TGz/m", z));
1447 stats.insert(std::make_pair(
"Odometry/TGroll/deg", roll*180.0/CV_PI));
1448 stats.insert(std::make_pair(
"Odometry/TGpitch/deg", pitch*180.0/CV_PI));
1449 stats.insert(std::make_pair(
"Odometry/TGyaw/deg", yaw*180.0/CV_PI));
1454 stats.insert(std::make_pair(
"Odometry/SpeedG/kph", speed*3.6));
1455 stats.insert(std::make_pair(
"Odometry/SpeedG/mph", speed*2.237));
1456 stats.insert(std::make_pair(
"Odometry/SpeedG/mps", speed));
1465 info.
lost = msg.lost;
1474 info.
reg.
covariance = cv::Mat(6,6,CV_64FC1, (
void*)msg.covariance.data()).clone();
1482 UASSERT(msg.localBundleModels.size() == msg.localBundleIds.size());
1483 UASSERT(msg.localBundleModels.size() == msg.localBundlePoses.size());
1484 for(
size_t i=0; i<msg.localBundleIds.size(); ++i)
1486 std::vector<rtabmap::CameraModel> models;
1487 for(
size_t j=0; j<msg.localBundleModels[i].models.size(); ++j)
1497 info.
stamp = msg.stamp;
1504 info.
type = msg.type;
1511 UASSERT(msg.wordsKeys.size() == msg.wordsValues.size());
1512 for(
unsigned int i=0; i<msg.wordsKeys.size(); ++i)
1526 UASSERT(msg.localMapKeys.size() == msg.localMapValues.size());
1527 for(
unsigned int i=0; i<msg.localMapKeys.size(); ++i)
1532 pcl::PCLPointCloud2 cloud;
1541 msg.lost = info.
lost;
1552 memcpy(msg.covariance.data(), info.
reg.
covariance.data, 36*
sizeof(double));
1562 for(std::map<
int, std::vector<rtabmap::CameraModel> >::const_iterator iter=info.
localBundleModels.begin();
1566 msg.localBundleIds.push_back(iter->first);
1569 geometry_msgs::Pose pose;
1571 msg.localBundlePoses.push_back(pose);
1573 rtabmap_ros::CameraModels models;
1574 for(
size_t i=0; i<iter->second.size(); ++i)
1576 rtabmap_ros::CameraModel modelMsg;
1579 models.models.push_back(modelMsg);
1581 msg.localBundleModels.push_back(models);
1586 msg.stamp = info.
stamp;
1593 msg.type = info.
type;
1622 if(!dataMsg.data.empty())
1624 if(dataMsg.cols > 0 && dataMsg.rows > 0 && dataMsg.type >= 0)
1626 data = cv::Mat(dataMsg.rows, dataMsg.cols, dataMsg.type, (
void*)dataMsg.data.data()).clone();
1630 if(dataMsg.cols != (
int)dataMsg.data.size() || dataMsg.rows != 1 || dataMsg.type != CV_8UC1)
1632 ROS_ERROR(
"cols, rows and type fields of the UserData msg " 1633 "are not correctly set (cols=%d, rows=%d, type=%d)! We assume that the data " 1634 "is compressed (cols=%d, rows=1, type=%d(CV_8UC1)).",
1635 dataMsg.cols, dataMsg.rows, dataMsg.type, (
int)dataMsg.data.size(), CV_8UC1);
1638 data = cv::Mat(1, dataMsg.data.size(), CV_8UC1, (
void*)dataMsg.data.data()).clone();
1643 void userDataToROS(
const cv::Mat & data, rtabmap_ros::UserData & dataMsg,
bool compress)
1651 dataMsg.cols = dataMsg.data.size();
1652 dataMsg.type = CV_8UC1;
1656 dataMsg.data.resize(data.step[0] * data.rows);
1657 memcpy(dataMsg.data.data(), data.data, dataMsg.data.size());
1658 dataMsg.rows = data.rows;
1659 dataMsg.cols = data.cols;
1660 dataMsg.type = data.type();
1666 const std::map<
int, std::pair<geometry_msgs::PoseWithCovarianceStamped, float> > & tags,
1668 const std::string & odomFrameId,
1671 double waitForTransform,
1672 double defaultLinVariance,
1673 double defaultAngVariance)
1677 for(std::map<
int, std::pair<geometry_msgs::PoseWithCovarianceStamped, float> >::const_iterator iter=tags.begin(); iter!=tags.end(); ++iter)
1681 ROS_ERROR(
"Invalid landmark received! IDs should be > 0 (it is %d). Ignoring this landmark.", iter->first);
1686 iter->second.first.header.frame_id,
1687 iter->second.first.header.stamp,
1691 if(baseToCamera.
isNull())
1693 ROS_ERROR(
"Cannot transform tag pose from \"%s\" frame to \"%s\" frame!",
1694 iter->second.first.header.frame_id.c_str(), frameId.c_str());
1706 iter->second.first.header.stamp,
1712 baseToTag = correction * baseToTag;
1716 ROS_WARN(
"Could not adjust tag pose accordingly to latest odometry pose. " 1717 "If odometry is small since it received the tag pose and " 1718 "covariance is large, this should not be a problem.");
1720 cv::Mat
covariance = cv::Mat(6,6, CV_64FC1, (
void*)iter->second.first.pose.covariance.data()).clone();
1721 if(covariance.empty() || !
uIsFinite(covariance.at<
double>(0,0)) || covariance.at<
double>(0,0)<=0.0
f)
1723 covariance = cv::Mat::eye(6,6,CV_64FC1);
1724 covariance(cv::Range(0,3), cv::Range(0,3)) *= defaultLinVariance;
1725 covariance(cv::Range(3,6), cv::Range(3,6)) *= defaultAngVariance;
1727 landmarks.insert(std::make_pair(iter->first,
rtabmap::Landmark(iter->first, iter->second.second, baseToTag, covariance)));
1734 const std::string & fromFrameId,
1735 const std::string & toFrameId,
1738 double waitForTransform)
1744 if(waitForTransform > 0.0 && !stamp.
isZero())
1747 std::string errorMsg;
1750 ROS_WARN(
"Could not get transform from %s to %s after %f seconds (for stamp=%f)! Error=\"%s\".",
1751 fromFrameId.c_str(), toFrameId.c_str(), waitForTransform, stamp.
toSec(), errorMsg.c_str());
1762 ROS_WARN(
"(getting transform %s -> %s) %s", fromFrameId.c_str(), toFrameId.c_str(), ex.what());
1770 const std::string & sourceTargetFrame,
1775 double waitForTransform)
1781 ros::Time stamp = stampSource>stampTarget?stampSource:stampTarget;
1782 if(waitForTransform > 0.0 && !stamp.
isZero())
1784 std::string errorMsg;
1787 ROS_WARN(
"Could not get transform from %s to %s accordingly to %s after %f seconds (for stamps=%f -> %f)! Error=\"%s\".",
1788 sourceTargetFrame.c_str(), sourceTargetFrame.c_str(), fixedFrame.c_str(), waitForTransform, stampSource.
toSec(), stampTarget.
toSec(), errorMsg.c_str());
1794 listener.
lookupTransform(sourceTargetFrame, stampTarget, sourceTargetFrame, stampSource, fixedFrame, tmp);
1799 ROS_WARN(
"(getting transform movement of %s according to fixed %s) %s", sourceTargetFrame.c_str(), fixedFrame.c_str(), ex.what());
1805 const std::vector<cv_bridge::CvImageConstPtr> & imageMsgs,
1806 const std::vector<cv_bridge::CvImageConstPtr> & depthMsgs,
1807 const std::vector<sensor_msgs::CameraInfo> & cameraInfoMsgs,
1808 const std::vector<sensor_msgs::CameraInfo> & depthCameraInfoMsgs,
1810 const std::string & odomFrameId,
1814 std::vector<rtabmap::CameraModel> & cameraModels,
1815 std::vector<rtabmap::StereoCameraModel> & stereoCameraModels,
1817 double waitForTransform,
1818 bool alreadRectifiedImages,
1819 const std::vector<std::vector<rtabmap_ros::KeyPoint> > & localKeyPointsMsgs,
1820 const std::vector<std::vector<rtabmap_ros::Point3f> > & localPoints3dMsgs,
1821 const std::vector<cv::Mat> & localDescriptorsMsgs,
1822 std::vector<cv::KeyPoint> * localKeyPoints,
1823 std::vector<cv::Point3f> * localPoints3d,
1824 cv::Mat * localDescriptors)
1826 UASSERT(!cameraInfoMsgs.empty() &&
1827 (cameraInfoMsgs.size() == imageMsgs.size() || imageMsgs.empty()) &&
1828 (cameraInfoMsgs.size() == depthMsgs.size() || depthMsgs.empty()) &&
1829 (cameraInfoMsgs.size() == depthCameraInfoMsgs.size() || depthCameraInfoMsgs.empty()));
1831 int imageWidth = imageMsgs.size()?imageMsgs[0]->image.cols:cameraInfoMsgs[0].width;
1832 int imageHeight = imageMsgs.size()?imageMsgs[0]->image.rows:cameraInfoMsgs[0].height;
1833 int depthWidth = depthMsgs.size()?depthMsgs[0]->image.cols:0;
1834 int depthHeight = depthMsgs.size()?depthMsgs[0]->image.rows:0;
1836 bool isDepth = depthMsgs.empty() || (depthMsgs[0].get() != 0 && (
1843 !depthMsgs.empty() &&
1845 cameraInfoMsgs.size() == depthCameraInfoMsgs.size())
1847 isDepth = cameraInfoMsgs[0].P.elems[3] == 0.0 && depthCameraInfoMsgs[0].P.elems[3] == 0.0;
1848 static bool warned =
false;
1849 if(!warned && isDepth)
1851 ROS_WARN(
"Input depth/left image has encoding \"mono16\" and " 1852 "camera info P[3] is null for both cameras, thus image is " 1853 "considered a depth image. If the depth image is in " 1854 "fact the right image, please convert the right image to " 1855 "\"mono8\". This warning is shown only once.");
1860 if(isDepth && !depthMsgs.empty())
1863 imageWidth/depthWidth == imageHeight/depthHeight,
1864 uFormat(
"rgb=%dx%d depth=%dx%d", imageWidth, imageHeight, depthWidth, depthHeight).c_str());
1867 int cameraCount = cameraInfoMsgs.size();
1868 for(
unsigned int i=0; i<cameraInfoMsgs.size(); ++i)
1870 if(!imageMsgs.empty())
1882 ROS_ERROR(
"Input rgb/left type must be image=mono8,mono16,rgb8,bgr8,bgra8,rgba8. Current rgb/left=%s",
1883 imageMsgs[i]->encoding.c_str());
1887 UASSERT_MSG(imageMsgs[i]->image.cols == imageWidth && imageMsgs[i]->image.rows == imageHeight,
1888 uFormat(
"imageWidth=%d vs %d imageHeight=%d vs %d",
1890 imageMsgs[i]->image.cols,
1892 imageMsgs[i]->image.rows).c_str());
1894 if(!depthMsgs.empty())
1901 ROS_ERROR(
"Input depth type must be image_depth=32FC1,16UC1,mono16. Current depth=%s",
1902 depthMsgs[i]->encoding.c_str());
1914 ROS_ERROR(
"Input right type must be image=mono8,mono16,rgb8,bgr8,bgra8,rgba8. Current right=%s",
1915 depthMsgs[i]->encoding.c_str());
1922 if(isDepth && !depthMsgs.empty())
1924 UASSERT_MSG(depthMsgs[i]->image.cols == depthWidth && depthMsgs[i]->image.rows == depthHeight,
1925 uFormat(
"depthWidth=%d vs %d imageHeight=%d vs %d",
1927 depthMsgs[i]->image.cols,
1929 depthMsgs[i]->image.rows).c_str());
1930 stamp = depthMsgs[i]->header.stamp;
1932 else if(!imageMsgs.empty())
1934 stamp = imageMsgs[i]->header.stamp;
1938 stamp = cameraInfoMsgs[i].header.stamp;
1943 if(localTransform.
isNull())
1945 ROS_ERROR(
"TF of received image %d at time %fs is not set!", i, stamp.
toSec());
1949 if(!odomFrameId.empty() && odomStamp !=
stamp)
1960 ROS_WARN(
"Could not get odometry value for image stamp (%fs). Latest odometry " 1961 "stamp is %fs. The image pose will not be synchronized with odometry.", stamp.
toSec(), odomStamp.
toSec());
1966 localTransform = sensorT * localTransform;
1970 if(!imageMsgs.empty())
1991 rgb = cv::Mat(imageHeight, imageWidth*cameraCount, ptrImage->image.type());
1993 if(ptrImage->image.type() == rgb.type())
1995 ptrImage->image.copyTo(cv::Mat(rgb, cv::Rect(i*imageWidth, 0, imageWidth, imageHeight)));
1999 ROS_ERROR(
"Some RGB/left images are not the same type!");
2004 if(!depthMsgs.empty())
2009 cv::Mat subDepth = ptrDepth->image;
2013 depth = cv::Mat(depthHeight, depthWidth*cameraCount, subDepth.type());
2016 if(subDepth.type() == depth.type())
2018 subDepth.copyTo(cv::Mat(depth, cv::Rect(i*depthWidth, 0, depthWidth, depthHeight)));
2022 ROS_ERROR(
"Some Depth images are not the same type!");
2042 depth = cv::Mat(depthHeight, depthWidth*cameraCount, ptrImage->image.type());
2044 if(ptrImage->image.type() == depth.type())
2046 ptrImage->image.copyTo(cv::Mat(depth, cv::Rect(i*depthWidth, 0, depthWidth, depthHeight)));
2050 ROS_ERROR(
"Some right images are not the same type!");
2062 UASSERT(cameraInfoMsgs.size() == depthCameraInfoMsgs.size());
2064 if(!alreadRectifiedImages)
2066 if(depthCameraInfoMsgs[i].
header.frame_id.empty() || cameraInfoMsgs[i].header.frame_id.empty())
2068 if(depthCameraInfoMsgs[i].
P[3] == 0.0 && cameraInfoMsgs[i].
P[3] == 0)
2070 ROS_ERROR(
"Parameter %s is false but the frame_id in one of the camera_info " 2071 "topic is empty, so TF between the cameras cannot be computed!",
2072 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str());
2077 static bool warned =
false;
2080 ROS_WARN(
"Parameter %s is false but the frame_id in one of the " 2081 "camera_info topic is empty, so TF between the cameras cannot be " 2082 "computed! However, the baseline can be computed from the calibration, " 2083 "we will use this one instead of TF. This message is only printed once...",
2084 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str());
2092 depthCameraInfoMsgs[i].
header.frame_id,
2093 cameraInfoMsgs[i].header.frame_id,
2094 cameraInfoMsgs[i].header.stamp,
2097 if(stereoTransform.isNull())
2099 ROS_ERROR(
"Parameter %s is false but we cannot get TF between the two cameras!", rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str());
2109 static bool shown =
false;
2112 ROS_WARN(
"Detected baseline (%f m) is quite large! Is your " 2113 "right camera_info P(0,3) correctly set? Note that " 2114 "baseline=-P(0,3)/P(0,0). You may need to calibrate your camera. " 2115 "This warning is printed only once.",
2120 else if(stereoModel.
baseline() == 0 && alreadRectifiedImages)
2123 if( !cameraInfoMsgs[i].
header.frame_id.empty() &&
2124 !depthCameraInfoMsgs[i].header.frame_id.empty())
2127 cameraInfoMsgs[i].
header.frame_id,
2128 depthCameraInfoMsgs[i].header.frame_id,
2129 cameraInfoMsgs[i].header.stamp,
2133 if(stereoTransform.
isNull() || stereoTransform.
x()<=0)
2135 if(cameraInfoMsgs[i].
header.frame_id.empty() || depthCameraInfoMsgs[i].header.frame_id.empty())
2137 ROS_WARN(
"We cannot estimated the baseline of the rectified images with tf! (camera_info topics have empty frame_id)");
2141 ROS_WARN(
"We cannot estimated the baseline of the rectified images with tf! (%s->%s = %s)",
2142 depthCameraInfoMsgs[i].
header.frame_id.c_str(), cameraInfoMsgs[i].header.frame_id.c_str(), stereoTransform.
prettyPrint().c_str());
2147 static bool warned =
false;
2150 ROS_WARN(
"Right camera info doesn't have Tx set but we are assuming that stereo images are already rectified (see %s parameter). While not " 2151 "recommended, we used TF to get the baseline (%s->%s = %fm) for convenience (e.g., D400 ir stereo issue). It is preferred to feed " 2152 "a valid right camera info if stereo images are already rectified. This message is only printed once...",
2153 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str(),
2154 depthCameraInfoMsgs[i].
header.frame_id.c_str(), cameraInfoMsgs[i].header.frame_id.c_str(), stereoTransform.
x());
2162 stereoTransform.
x(),
2167 stereoCameraModels.push_back(stereoModel);
2170 if(localKeyPoints && localKeyPointsMsgs.size() == cameraInfoMsgs.size())
2174 if(localPoints3d && localPoints3dMsgs.size() == cameraInfoMsgs.size())
2179 if(localDescriptors && localDescriptorsMsgs.size() == cameraInfoMsgs.size())
2181 localDescriptors->push_back(localDescriptorsMsgs[i]);
2190 const sensor_msgs::CameraInfo& leftCamInfoMsg,
2191 const sensor_msgs::CameraInfo& rightCamInfoMsg,
2193 const std::string & odomFrameId,
2199 double waitForTransform,
2200 bool alreadyRectified)
2202 UASSERT(leftImageMsg.get() && rightImageMsg.get());
2219 ROS_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8,bgra8,rgba8");
2220 ROS_ERROR(
"Input type must be image=mono8,mono16,rgb8,bgr8,bgra8,rgba8 Current left=%s and right=%s",
2221 leftImageMsg->encoding.c_str(),
2222 rightImageMsg->encoding.c_str());
2229 left = leftImageMsg->image.clone();
2242 right = rightImageMsg->image.clone();
2249 rtabmap::Transform localTransform =
getTransform(frameId, leftImageMsg->header.frame_id, leftImageMsg->header.stamp, listener, waitForTransform);
2250 if(localTransform.
isNull())
2255 if(!odomFrameId.empty() && odomStamp != leftImageMsg->header.stamp)
2261 leftImageMsg->header.stamp,
2266 ROS_WARN(
"Could not get odometry value for stereo msg stamp (%fs). Latest odometry " 2267 "stamp is %fs. The stereo image pose will not be synchronized with odometry.", leftImageMsg->header.stamp.toSec(), odomStamp.
toSec());
2271 localTransform = sensorT * localTransform;
2276 if(!alreadyRectified)
2279 rightCamInfoMsg.header.frame_id,
2280 leftCamInfoMsg.header.frame_id,
2281 leftCamInfoMsg.header.stamp,
2284 if(stereoTransform.
isNull())
2286 ROS_ERROR(
"Parameter %s is false but we cannot get TF between the two cameras!", rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str());
2295 static bool shown =
false;
2298 ROS_WARN(
"Detected baseline (%f m) is quite large! Is your " 2299 "right camera_info P(0,3) correctly set? Note that " 2300 "baseline=-P(0,3)/P(0,0). You may need to calibrate your camera. " 2301 "This warning is printed only once.",
2306 else if(stereoModel.
baseline() == 0 && alreadyRectified)
2309 leftCamInfoMsg.header.frame_id,
2310 rightCamInfoMsg.header.frame_id,
2311 leftCamInfoMsg.header.stamp,
2314 if(stereoTransform.
isNull() || stereoTransform.
x()<=0)
2316 ROS_WARN(
"We cannot estimated the baseline of the rectified images with tf! (%s->%s = %s)",
2317 rightCamInfoMsg.header.frame_id.c_str(), leftCamInfoMsg.header.frame_id.c_str(), stereoTransform.
prettyPrint().c_str());
2321 static bool warned =
false;
2324 ROS_WARN(
"Right camera info doesn't have Tx set but we are assuming that stereo images are already rectified (see %s parameter). While not " 2325 "recommended, we used TF to get the baseline (%s->%s = %fm) for convenience (e.g., D400 ir stereo issue). It is preferred to feed " 2326 "a valid right camera info if stereo images are already rectified. This message is only printed once...",
2327 rtabmap::Parameters::kRtabmapImagesAlreadyRectified().c_str(),
2328 rightCamInfoMsg.header.frame_id.c_str(), leftCamInfoMsg.header.frame_id.c_str(), stereoTransform.
x());
2336 stereoTransform.
x(),
2345 const sensor_msgs::LaserScan & scan2dMsg,
2347 const std::string & odomFrameId,
2351 double waitForTransform,
2352 bool outputInFrameId)
2356 scan2dMsg.header.frame_id,
2357 odomFrameId.empty()?
frameId:odomFrameId,
2358 scan2dMsg.header.stamp,
2359 scan2dMsg.header.stamp +
ros::Duration().
fromSec(scan2dMsg.ranges.size()*scan2dMsg.time_increment),
2369 scan2dMsg.header.frame_id,
2370 scan2dMsg.header.stamp,
2373 if(scanLocalTransform.
isNull())
2379 sensor_msgs::PointCloud2 scanOut;
2385 scan2dMsg.header.frame_id,
2386 odomFrameId.empty()?
frameId:odomFrameId,
2387 scan2dMsg.header.stamp,
2396 if(!odomFrameId.empty() && odomStamp != scan2dMsg.header.stamp)
2402 scan2dMsg.header.stamp,
2407 ROS_WARN(
"Could not get odometry value for laser scan stamp (%fs). Latest odometry " 2408 "stamp is %fs. The laser scan pose will not be synchronized with odometry.", scan2dMsg.header.stamp.toSec(), odomStamp.
toSec());
2413 scanLocalTransform = sensorT * scanLocalTransform;
2419 laserToOdom *= scanLocalTransform;
2422 bool hasIntensity =
false;
2423 for(
unsigned int i=0; i<scanOut.fields.size(); ++i)
2425 if(scanOut.fields[i].name.compare(
"intensity") == 0)
2427 if(scanOut.fields[i].datatype == sensor_msgs::PointField::FLOAT32)
2429 hasIntensity =
true;
2433 static bool warningShown =
false;
2436 ROS_WARN(
"The input scan cloud has an \"intensity\" field " 2437 "but the datatype (%d) is not supported. Intensity will be ignored. " 2438 "This message is only shown once.", scanOut.fields[i].datatype);
2439 warningShown =
true;
2449 pcl::PointCloud<pcl::PointXYZI>::Ptr pclScan(
new pcl::PointCloud<pcl::PointXYZI>);
2451 pclScan->is_dense =
true;
2457 pcl::PointCloud<pcl::PointXYZ>::Ptr pclScan(
new pcl::PointCloud<pcl::PointXYZ>);
2459 pclScan->is_dense =
true;
2465 if((scanLocalTransform.
rotation()*zAxis).
z() < 0)
2468 cv::flip(data, flipScan, 1);
2475 scan2dMsg.range_min,
2476 scan2dMsg.range_max,
2477 scan2dMsg.angle_min,
2478 scan2dMsg.angle_max,
2479 scan2dMsg.angle_increment,
2486 const sensor_msgs::PointCloud2 & scan3dMsg,
2488 const std::string & odomFrameId,
2492 double waitForTransform,
2497 UASSERT_MSG(scan3dMsg.data.size() == scan3dMsg.row_step*scan3dMsg.height,
2498 uFormat(
"data=%d row_step=%d height=%d", scan3dMsg.data.size(), scan3dMsg.row_step, scan3dMsg.height).c_str());
2501 if(scanLocalTransform.isNull())
2503 ROS_ERROR(
"TF of received scan cloud at time %fs is not set, aborting rtabmap update.", scan3dMsg.header.stamp.toSec());
2508 if(!odomFrameId.empty() && odomStamp != scan3dMsg.header.stamp)
2514 scan3dMsg.header.stamp,
2519 ROS_WARN(
"Could not get odometry value for laser scan stamp (%fs). Latest odometry " 2520 "stamp is %fs. The 3d laser scan pose will not be synchronized with odometry.", scan3dMsg.header.stamp.toSec(), odomStamp.
toSec());
2524 scanLocalTransform = sensorT * scanLocalTransform;
2533 const sensor_msgs::PointCloud2 & input,
2534 sensor_msgs::PointCloud2 & output,
2535 const std::string & fixedFrameId,
2537 double waitForTransform,
2540 double previousStamp)
2544 if(input.header.frame_id.empty())
2546 ROS_ERROR(
"Input cloud has empty frame_id!");
2550 if(fixedFrameId.empty())
2552 ROS_ERROR(
"fixedFrameId parameter should be set!");
2560 ROS_ERROR(
"slerp should be true when constant velocity model is used!");
2564 if(previousStamp <= 0.0)
2566 ROS_ERROR(
"previousStamp should be >0 when constant velocity model is used!");
2572 ROS_ERROR(
"velocity should be valid when constant velocity model is used!");
2577 int offsetTime = -1;
2581 int timeDatatype = 6;
2582 for(
size_t i=0; i<input.fields.size(); ++i)
2584 if(input.fields[i].name.compare(
"t") == 0)
2586 if(offsetTime != -1)
2588 ROS_WARN(
"The input cloud should have only one of these fields: t, time or stamps. Overriding with %s.", input.fields[i].name.c_str());
2590 offsetTime = input.fields[i].offset;
2591 timeDatatype = input.fields[i].datatype;
2593 else if(input.fields[i].name.compare(
"time") == 0)
2595 if(offsetTime != -1)
2597 ROS_WARN(
"The input cloud should have only one of these fields: t, time or stamps. Overriding with %s.", input.fields[i].name.c_str());
2599 offsetTime = input.fields[i].offset;
2600 timeDatatype = input.fields[i].datatype;
2602 else if(input.fields[i].name.compare(
"stamps") == 0)
2604 if(offsetTime != -1)
2606 ROS_WARN(
"The input cloud should have only one of these fields: t, time or stamps. Overriding with %s.", input.fields[i].name.c_str());
2608 offsetTime = input.fields[i].offset;
2609 timeDatatype = input.fields[i].datatype;
2611 else if(input.fields[i].name.compare(
"x") == 0)
2614 offsetX = input.fields[i].offset;
2616 else if(input.fields[i].name.compare(
"y") == 0)
2619 offsetY = input.fields[i].offset;
2621 else if(input.fields[i].name.compare(
"z") == 0)
2624 offsetZ = input.fields[i].offset;
2630 ROS_ERROR(
"Input cloud doesn't have \"t\" or \"time\" field!");
2635 ROS_ERROR(
"Input cloud doesn't have \"x\" field!");
2640 ROS_ERROR(
"Input cloud doesn't have \"y\" field!");
2645 ROS_ERROR(
"Input cloud doesn't have \"z\" field!");
2648 if(input.height == 0)
2650 ROS_ERROR(
"Input cloud height is zero!");
2653 if(input.width == 0)
2655 ROS_ERROR(
"Input cloud width is zero!");
2659 bool timeOnColumns = input.width > input.height;
2664 if(timeDatatype == 6)
2666 unsigned int nsec = *((
const unsigned int*)(&input.data[0]+offsetTime));
2668 nsec = *((
const unsigned int*)(&input.data[timeOnColumns?(input.width-1)*input.point_step:(input.height-1)*input.row_step]+offsetTime));
2671 else if(timeDatatype == 7)
2673 float sec = *((
const float*)(&input.data[0]+offsetTime));
2675 sec = *((
const float*)(&input.data[timeOnColumns?(input.width-1)*input.point_step:(input.height-1)*input.row_step]+offsetTime));
2680 ROS_ERROR(
"Not supported time datatype %d!", timeDatatype);
2684 if(lastStamp <= firstStamp)
2686 ROS_ERROR(
"First and last stamps in the scan are the same!");
2690 std::string errorMsg;
2692 waitForTransform>0.0 &&
2694 input.header.frame_id,
2696 input.header.frame_id,
2703 ROS_ERROR(
"Could not estimate motion of %s accordingly to fixed frame %s between stamps %f and %f! (%s)",
2704 input.header.frame_id.c_str(),
2705 fixedFrameId.c_str(),
2714 double scanTime = 0;
2720 input.header.frame_id,
2727 input.header.frame_id,
2736 float vx,vy,vz, vroll,vpitch,vyaw;
2745 double dt1 = firstStamp.
toSec() - previousStamp;
2746 double dt2 = input.header.stamp.toSec() - previousStamp;
2747 double dt3 = lastStamp.
toSec() - previousStamp;
2754 firstPose = p2.
inverse() * p1;
2760 ROS_ERROR(
"Could not get transform of %s accordingly to %s between stamps %f and %f!",
2761 input.header.frame_id.c_str(),
2762 fixedFrameId.empty()?
"velocity":fixedFrameId.c_str(),
2764 input.header.stamp.toSec());
2769 ROS_ERROR(
"Could not get transform of %s accordingly to %s between stamps %f and %f!",
2770 input.header.frame_id.c_str(),
2771 fixedFrameId.empty()?
"velocity":fixedFrameId.c_str(),
2773 input.header.stamp.toSec());
2776 scanTime = lastStamp.
toSec() - firstStamp.
toSec();
2791 for(
size_t u=0; u<output.width; ++u)
2793 if(timeDatatype == 6)
2795 unsigned int nsec = *((
const unsigned int*)(&output.data[u*output.point_step]+offsetTime));
2800 float sec = *((
const float*)(&output.data[u*output.point_step]+offsetTime));
2807 transform = firstPose.
interpolate((stamp-firstStamp).toSec() / scanTime, lastPose);
2812 output.header.frame_id,
2815 output.header.stamp,
2820 ROS_ERROR(
"Could not get transform of %s accordingly to %s between stamps %f and %f!",
2821 output.header.frame_id.c_str(),
2822 fixedFrameId.c_str(),
2824 output.header.stamp.toSec());
2829 for(
size_t v=0; v<input.height; ++v)
2831 unsigned char * dataPtr = &output.data[v*output.row_step + u*output.point_step];
2832 float &
x = *((
float*)(dataPtr+offsetX));
2833 float &
y = *((
float*)(dataPtr+offsetY));
2834 float &
z = *((
float*)(dataPtr+offsetZ));
2835 pcl::PointXYZ
pt(x,y,z);
2842 if(timeDatatype == 6)
2844 *((
unsigned int*)(dataPtr+offsetTime)) = 0;
2848 *((
float*)(dataPtr+offsetTime)) = 0;
2861 for(
size_t v=0; v<output.height; ++v)
2863 if(timeDatatype == 6)
2865 unsigned int nsec = *((
const unsigned int*)(&output.data[v*output.row_step]+offsetTime));
2870 float sec = *((
const float*)(&output.data[v*output.row_step]+offsetTime));
2877 transform = firstPose.
interpolate((stamp-firstStamp).toSec() / scanTime, lastPose);
2882 output.header.frame_id,
2885 output.header.stamp,
2890 ROS_ERROR(
"Could not get transform of %s accordingly to %s between stamps %f and %f!",
2891 output.header.frame_id.c_str(),
2892 fixedFrameId.c_str(),
2894 output.header.stamp.toSec());
2899 for(
size_t u=0; u<input.width; ++u)
2901 unsigned char * dataPtr = &output.data[v*output.row_step + u*output.point_step];
2902 float &
x = *((
float*)(dataPtr+offsetX));
2903 float &
y = *((
float*)(dataPtr+offsetY));
2904 float &
z = *((
float*)(dataPtr+offsetZ));
2905 pcl::PointXYZ
pt(x,y,z);
2912 if(timeDatatype == 6)
2914 *((
unsigned int*)(dataPtr+offsetTime)) = 0;
2918 *((
float*)(dataPtr+offsetTime)) = 0;
2928 const sensor_msgs::PointCloud2 & input,
2929 sensor_msgs::PointCloud2 & output,
2930 const std::string & fixedFrameId,
2932 double waitForTransform,
2939 const sensor_msgs::PointCloud2 & input,
2940 sensor_msgs::PointCloud2 & output,
2941 double previousStamp,
2944 return deskew_impl(input, output,
"", 0, 0,
true, velocity, previousStamp);
const cv::Mat & infMatrix() const
CvImageConstPtr toCvShare(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
void globalDescriptorsToROS(const std::vector< rtabmap::GlobalDescriptor > &desc, std::vector< rtabmap_ros::GlobalDescriptor > &msg)
const Type & type() const
const std::string BAYER_GRBG8
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
void keypointsToROS(const std::vector< cv::KeyPoint > &kpts, std::vector< rtabmap_ros::KeyPoint > &msg)
const std::vector< int > & wmState() const
void transformEigenToTF(const Eigen::Affine3d &e, tf::Transform &t)
bool isValidForProjection() const
const cv::Size & imageSize() const
std::vector< cv::Point2f > refCorners
const std::map< int, float > & posterior() const
const double & error() const
void transformToTF(const rtabmap::Transform &transform, tf::Transform &tfTransform)
cv::Mat RTABMAP_EXP uncompressData(const cv::Mat &bytes)
const cv::Mat & gridObstacleCellsCompressed() const
std::string uFormat(const char *fmt,...)
Transform transformGroundTruth
const double & stamp() const
cv::Point3f RTABMAP_EXP transformPoint(const cv::Point3f &pt, const Transform &transform)
const Transform & getGroundTruthPose() const
int currentGoalId() const
const std::vector< cv::Point3f > & keypoints3D() const
bool convertRGBDMsgs(const std::vector< cv_bridge::CvImageConstPtr > &imageMsgs, const std::vector< cv_bridge::CvImageConstPtr > &depthMsgs, const std::vector< sensor_msgs::CameraInfo > &cameraInfoMsgs, const std::vector< sensor_msgs::CameraInfo > &depthCameraInfoMsgs, const std::string &frameId, const std::string &odomFrameId, const ros::Time &odomStamp, cv::Mat &rgb, cv::Mat &depth, std::vector< rtabmap::CameraModel > &cameraModels, std::vector< rtabmap::StereoCameraModel > &stereoCameraModels, tf::TransformListener &listener, double waitForTransform, bool alreadRectifiedImages, const std::vector< std::vector< rtabmap_ros::KeyPoint > > &localKeyPointsMsgs=std::vector< std::vector< rtabmap_ros::KeyPoint > >(), const std::vector< std::vector< rtabmap_ros::Point3f > > &localPoints3dMsgs=std::vector< std::vector< rtabmap_ros::Point3f > >(), const std::vector< cv::Mat > &localDescriptorsMsgs=std::vector< cv::Mat >(), std::vector< cv::KeyPoint > *localKeyPoints=0, std::vector< cv::Point3f > *localPoints3d=0, cv::Mat *localDescriptors=0)
rtabmap::Signature nodeDataFromROS(const rtabmap_ros::NodeData &msg)
void transformTFToEigen(const tf::Transform &t, Eigen::Affine3d &e)
GLM_FUNC_DECL genType sec(genType const &angle)
rtabmap::EnvSensor envSensorFromROS(const rtabmap_ros::EnvSensor &msg)
const LaserScan & laserScanCompressed() const
void points2fToROS(const std::vector< cv::Point2f > &kpts, std::vector< rtabmap_ros::Point2f > &msg)
rtabmap::SensorData rgbdImageFromROS(const rtabmap_ros::RGBDImageConstPtr &image)
bool deskew_impl(const sensor_msgs::PointCloud2 &input, sensor_msgs::PointCloud2 &output, const std::string &fixedFrameId, tf::TransformListener *listener, double waitForTransform, bool slerp, const rtabmap::Transform &velocity, double previousStamp)
Transform transformFiltered
void mapGraphToROS(const std::map< int, rtabmap::Transform > &poses, const std::multimap< int, rtabmap::Link > &links, const rtabmap::Transform &mapToOdom, rtabmap_ros::MapGraph &msg)
void poseEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Pose &m)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
std::vector< rtabmap::GlobalDescriptor > globalDescriptorsFromROS(const std::vector< rtabmap_ros::GlobalDescriptor > &msg)
void setLoopClosureId(int id)
const cv::Mat & gridGroundCellsCompressed() const
std::map< int, cv::Point3f > localMap
void setLabels(const std::map< int, std::string > &labels)
void setPosterior(const std::map< int, float > &posterior)
void poseMsgToEigen(const geometry_msgs::Pose &m, Eigen::Affine3d &e)
void setRawLikelihood(const std::map< int, float > &rawLikelihood)
const cv::Mat & getWordsDescriptors() const
void setRefImageId(int id)
float inliersMeanDistance
const cv::Mat & depthOrRightRaw() const
std::map< int, std::vector< CameraModel > > localBundleModels
void odomInfoToROS(const rtabmap::OdometryInfo &info, rtabmap_ros::OdomInfo &msg, bool ignoreData=false)
void setProximityDetectionId(int id)
void transformEigenToMsg(const Eigen::Affine3d &e, geometry_msgs::Transform &m)
void transformToGeometryMsg(const rtabmap::Transform &transform, geometry_msgs::Transform &msg)
pcl::PCLPointCloud2::Ptr RTABMAP_EXP laserScanToPointCloud2(const LaserScan &laserScan, const Transform &transform=Transform())
rtabmap::Landmarks landmarksFromROS(const std::map< int, std::pair< geometry_msgs::PoseWithCovarianceStamped, float > > &tags, const std::string &frameId, const std::string &odomFrameId, const ros::Time &odomStamp, tf::TransformListener &listener, double waitForTransform, double defaultLinVariance, double defaultAngVariance)
std::map< int, Landmark > Landmarks
const std::vector< StereoCameraModel > & stereoCameraModels() const
rtabmap::Signature nodeInfoFromROS(const rtabmap_ros::NodeData &msg)
const cv::Mat & data() const
rtabmap::Transform transformFromPoseMsg(const geometry_msgs::Pose &msg, bool ignoreRotationIfNotSet=false)
const std::vector< cv::KeyPoint > & keypoints() const
const std::string TYPE_8UC1
const std::vector< cv::Point3f > & getWords3() const
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
const cv::Mat info() const
float timeParticleFiltering
void setCurrentGoalId(int goal)
std::vector< int > inliersIDs
const std::map< int, int > & weights() const
void nodeInfoToROS(const rtabmap::Signature &signature, rtabmap_ros::NodeData &msg)
void setOdomCacheConstraints(const std::multimap< int, Link > &constraints)
const std::string & getLabel() const
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
bool deskew(const sensor_msgs::PointCloud2 &input, sensor_msgs::PointCloud2 &output, const std::string &fixedFrameId, tf::TransformListener &listener, double waitForTransform, bool slerp=false)
int localBundleConstraints
const std::vector< GlobalDescriptor > & globalDescriptors() const
void points3fToROS(const std::vector< cv::Point3f > &pts, std::vector< rtabmap_ros::Point3f > &msg, const rtabmap::Transform &transform=rtabmap::Transform())
const Transform & loopClosureTransform() const
geometry_msgs::TransformStamped t
bool uStrContains(const std::string &string, const std::string &substring)
rtabmap::Transform getTransform(const std::string &fromFrameId, const std::string &toFrameId, const ros::Time &stamp, tf::TransformListener &listener, double waitForTransform)
const std::map< int, float > & likelihood() const
float gridCellSize() const
const std::map< std::string, float > & data() const
int loopClosureId() const
void point2fToROS(const cv::Point2f &kpt, rtabmap_ros::Point2f &msg)
bool uIsFinite(const T &value)
const std::vector< cv::KeyPoint > & getWordsKpts() const
#define UASSERT(condition)
cv::KeyPoint keypointFromROS(const rtabmap_ros::KeyPoint &msg)
void setLocalPath(const std::vector< int > &localPath)
const double & altitude() const
const double & bearing() const
sensor_msgs::ImagePtr toImageMsg() const
std::map< std::string, float > odomInfoToStatistics(const rtabmap::OdometryInfo &info)
const std::vector< CameraModel > & cameraModels() const
void mapDataFromROS(const rtabmap_ros::MapData &msg, std::map< int, rtabmap::Transform > &poses, std::multimap< int, rtabmap::Link > &links, std::map< int, rtabmap::Signature > &signatures, rtabmap::Transform &mapToOdom)
rtabmap::OdometryInfo odomInfoFromROS(const rtabmap_ros::OdomInfo &msg, bool ignoreData=false)
std::vector< int > cornerInliers
void setExtended(bool extended)
const std::map< int, float > & rawLikelihood() const
void linkToROS(const rtabmap::Link &link, rtabmap_ros::Link &msg)
rtabmap::Link linkFromROS(const rtabmap_ros::Link &msg)
#define UASSERT_MSG(condition, msg_str)
CvImagePtr cvtColor(const CvImageConstPtr &source, const std::string &encoding)
void rgbdImageToROS(const rtabmap::SensorData &data, rtabmap_ros::RGBDImage &msg, const std::string &sensorFrameId)
Duration & fromSec(double t)
const cv::Mat & imageRaw() const
GLM_FUNC_DECL detail::tquat< T, P > slerp(detail::tquat< T, P > const &x, detail::tquat< T, P > const &y, T const &a)
void mapDataToROS(const std::map< int, rtabmap::Transform > &poses, const std::multimap< int, rtabmap::Link > &links, const std::map< int, rtabmap::Signature > &signatures, const rtabmap::Transform &mapToOdom, rtabmap_ros::MapData &msg)
std::vector< unsigned char > RTABMAP_EXP compressData(const cv::Mat &data)
void envSensorsToROS(const rtabmap::EnvSensors &sensors, std::vector< rtabmap_ros::EnvSensor > &msg)
std::vector< cv::Point3f > points3fFromROS(const std::vector< rtabmap_ros::Point3f > &msg, const rtabmap::Transform &transform=rtabmap::Transform())
const EnvSensors & envSensors() const
cv::Point3f point3fFromROS(const rtabmap_ros::Point3f &msg)
const Transform & mapCorrection() const
void infoFromROS(const rtabmap_ros::Info &info, rtabmap::Statistics &stat)
const std::string TYPE_32FC1
void mapGraphFromROS(const rtabmap_ros::MapGraph &msg, std::map< int, rtabmap::Transform > &poses, std::multimap< int, rtabmap::Link > &links, rtabmap::Transform &mapToOdom)
const cv::Mat & descriptors() const
std::map< int, Transform > localBundlePoses
cv::Mat compressedMatFromBytes(const std::vector< unsigned char > &bytes, bool copy=true)
rtabmap::CameraModel cameraModelFromROS(const sensor_msgs::CameraInfo &camInfo, const rtabmap::Transform &localTransform=rtabmap::Transform::getIdentity())
std::vector< cv::KeyPoint > keypointsFromROS(const std::vector< rtabmap_ros::KeyPoint > &msg)
CvImagePtr toCvCopy(const sensor_msgs::ImageConstPtr &source, const std::string &encoding=std::string())
const std::string TYPE_16UC1
rtabmap::EnvSensors envSensorsFromROS(const std::vector< rtabmap_ros::EnvSensor > &msg)
const std::multimap< int, Link > & odomCacheConstraints() const
LaserScan laserScanFromPointCloud(const PointCloud2T &cloud, bool filterNaNs, bool is2D, const Transform &transform)
void toPCL(const ros::Time &stamp, std::uint64_t &pcl_stamp)
float icpStructuralDistribution
void cameraModelToROS(const rtabmap::CameraModel &model, sensor_msgs::CameraInfo &camInfo)
std::list< V > uValues(const std::multimap< K, V > &mm)
float inliersDistribution
const cv::Mat & depthOrRightCompressed() const
cv::Mat userDataFromROS(const rtabmap_ros::UserData &dataMsg)
bool convertStereoMsg(const cv_bridge::CvImageConstPtr &leftImageMsg, const cv_bridge::CvImageConstPtr &rightImageMsg, const sensor_msgs::CameraInfo &leftCamInfoMsg, const sensor_msgs::CameraInfo &rightCamInfoMsg, const std::string &frameId, const std::string &odomFrameId, const ros::Time &odomStamp, cv::Mat &left, cv::Mat &right, rtabmap::StereoCameraModel &stereoModel, tf::TransformListener &listener, double waitForTransform, bool alreadyRectified)
void setLikelihood(const std::map< int, float > &likelihood)
void transformToPoseMsg(const rtabmap::Transform &transform, geometry_msgs::Pose &msg)
void keypointToROS(const cv::KeyPoint &kpt, rtabmap_ros::KeyPoint &msg)
const cv::Mat data() const
const std::vector< int > & localPath() const
const cv::Point3f & gridViewPoint() const
bool convertScanMsg(const sensor_msgs::LaserScan &scan2dMsg, const std::string &frameId, const std::string &odomFrameId, const ros::Time &odomStamp, rtabmap::LaserScan &scan, tf::TransformListener &listener, double waitForTransform, bool outputInFrameId=false)
void setWmState(const std::vector< int > &state)
void transformMsgToEigen(const geometry_msgs::Transform &m, Eigen::Affine3d &e)
const Transform & localTransform() const
rtabmap::GlobalDescriptor globalDescriptorFromROS(const rtabmap_ros::GlobalDescriptor &msg)
void setStamp(double stamp)
std::multimap< int, cv::KeyPoint > words
SensorData & sensorData()
float icpStructuralComplexity
const double & longitude() const
std::list< K > uKeys(const std::multimap< K, V > &mm)
void toCvShare(const rtabmap_ros::RGBDImageConstPtr &image, cv_bridge::CvImageConstPtr &rgb, cv_bridge::CvImageConstPtr &depth)
void setWeights(const std::map< int, int > &weights)
std::vector< cv::Point2f > points2fFromROS(const std::vector< rtabmap_ros::Point2f > &msg)
const cv::Mat & userDataCompressed() const
const Transform & getPose() const
void globalDescriptorToROS(const rtabmap::GlobalDescriptor &desc, rtabmap_ros::GlobalDescriptor &msg)
rtabmap::StereoCameraModel stereoCameraModelFromROS(const sensor_msgs::CameraInfo &leftCamInfo, const sensor_msgs::CameraInfo &rightCamInfo, const rtabmap::Transform &localTransform=rtabmap::Transform::getIdentity(), const rtabmap::Transform &stereoTransform=rtabmap::Transform())
void envSensorToROS(const rtabmap::EnvSensor &sensor, rtabmap_ros::EnvSensor &msg)
const double & stamp() const
double timestampFromROS(const ros::Time &stamp)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
std::vector< int > matchesIDs
std::vector< cv::Point2f > newCorners
const std::string BAYER_RGGB8
void setLoopClosureTransform(const Transform &loopClosureTransform)
void toCvCopy(const rtabmap_ros::RGBDImage &image, cv_bridge::CvImagePtr &rgb, cv_bridge::CvImagePtr &depth)
void userDataToROS(const cv::Mat &data, rtabmap_ros::UserData &dataMsg, bool compress)
void compressedMatToBytes(const cv::Mat &compressed, std::vector< unsigned char > &bytes)
const double & latitude() const
void transformLaserScanToPointCloud(const std::string &target_frame, const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, tf::Transformer &tf, double range_cutoff, int channel_options=channel_option::Default)
std::map< EnvSensor::Type, EnvSensor > EnvSensors
const std::map< int, std::string > & labels() const
void moveFromPCL(pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
int proximityDetectionId() const
const Transform & transform() const
rtabmap::Transform transformFromGeometryMsg(const geometry_msgs::Transform &msg)
const cv::Mat & gridEmptyCellsCompressed() const
const double & value() const
void nodeDataToROS(const rtabmap::Signature &signature, rtabmap_ros::NodeData &msg)
rtabmap::Transform transformFromTF(const tf::Transform &transform)
const cv::Mat & imageCompressed() const
Transform localTransform() const
bool convertScan3dMsg(const sensor_msgs::PointCloud2 &scan3dMsg, const std::string &frameId, const std::string &odomFrameId, const ros::Time &odomStamp, rtabmap::LaserScan &scan, tf::TransformListener &listener, double waitForTransform, int maxPoints=0, float maxRange=0.0f, bool is2D=false)
LaserScan RTABMAP_EXP laserScan2dFromPointCloud(const pcl::PointCloud< pcl::PointXYZ > &cloud, const Transform &transform=Transform(), bool filterNaNs=true)
void point3fToROS(const cv::Point3f &pt, rtabmap_ros::Point3f &msg)
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
cv::Point2f point2fFromROS(const rtabmap_ros::Point2f &msg)
const std::map< int, Transform > & odomCachePoses() const
void infoToROS(const rtabmap::Statistics &stats, rtabmap_ros::Info &info)
cv::Mat RTABMAP_EXP uncompressImage(const cv::Mat &bytes)
void setOdomCachePoses(const std::map< int, Transform > &poses)
void addStatistic(const std::string &name, float value)
const std::multimap< int, int > & getWords() const
const CameraModel & left() const