39 #include <pcl/search/kdtree.h> 40 #include <pcl/common/eigen.h> 41 #include <pcl/common/common.h> 42 #include <pcl/common/point_tests.h> 55 const std::string & filePath,
57 const std::map<int, Transform> & poses,
58 const std::multimap<int, Link> & constraints,
59 const std::map<int, double> & stamps,
62 UDEBUG(
"%s", filePath.c_str());
63 std::string tmpPath = filePath;
71 return toro.
saveGraph(tmpPath, poses, constraints);
80 return g2o.
saveGraph(tmpPath, poses, constraints);
89 if(format == 1 || format == 10 || format == 11)
91 if(stamps.size() != poses.size())
93 UERROR(
"When exporting poses to format 1 (RGBD-SLAM), stamps and poses maps should have the same size! stamps=%d poses=%d",
94 (
int)stamps.size(), (int)poses.size());
101 fopen_s(&fout, tmpPath.c_str(),
"w");
103 fout = fopen(tmpPath.c_str(),
"w");
107 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
109 if(format == 1 || format == 10 || format == 11)
128 if(iter == poses.begin())
133 fprintf(fout,
"#timestamp x y z qx qy qz qw id\n");
137 fprintf(fout,
"#timestamp x y z qx qy qz qw\n");
142 fprintf(fout,
"%f %f %f %f %f %f %f %f%s\n",
143 stamps.at(iter->first),
151 format == 11?(
" "+
uNumber2Str(iter->first)).c_str():
"");
167 const float * p = (
const float *)pose.
data();
169 fprintf(fout,
"%f", p[0]);
170 for(
int i=1; i<pose.
size(); i++)
172 fprintf(fout,
" %f", p[i]);
185 const std::string & filePath,
187 std::map<int, Transform> & poses,
188 std::multimap<int, Link> * constraints,
189 std::map<int, double> * stamps)
191 UDEBUG(
"%s format=%d", filePath.c_str(), format);
194 std::multimap<int, Link> constraintsTmp;
199 *constraints = constraintsTmp;
207 std::multimap<int, Link> constraintsTmp;
208 UERROR(
"Cannot import from g2o format because it is not yet supported!");
214 file.open(filePath.c_str(), std::ifstream::in);
225 std::getline(file, str);
227 if(str.size() && str.at(str.size()-1) ==
'\r')
229 str = str.substr(0, str.size()-1);
232 if(str.empty() || str.at(0) ==
'#' || str.at(0) ==
'%')
239 std::list<std::string> strList =
uSplit(str,
',');
240 if(strList.size() == 17)
242 double stamp =
uStr2Double(strList.front())/1000000000.0;
249 UWARN(
"Null transform read!? line parsed: \"%s\"", str.c_str());
255 stamps->insert(std::make_pair(
id, stamp));
262 poses.insert(std::make_pair(
id, pose));
267 UERROR(
"Error parsing \"%s\" with EuRoC MAV format (should have 17 values: stamp x y z qw qx qy qz vx vy vz vr vp vy ax ay az)", str.c_str());
273 if(strList.size() == 10)
278 double stamp =
uStr2Double(strList[0].insert(10, 1,
'.'));
287 stamps->insert(std::make_pair(
id, stamp));
290 if(poses.size() == 0)
294 pose = originPose * pose;
295 poses.insert(std::make_pair(
id, pose));
299 UERROR(
"Error parsing \"%s\" with Karlsruhe format (should have 10 values)", str.c_str());
305 if(strList.size() == 12)
322 std::string millisecStr = strList[1];
323 while(millisecStr.size() < 6)
325 millisecStr =
"0" + millisecStr;
327 double stamp =
uStr2Double(strList[0] +
"." + millisecStr);
343 stamps->insert(std::make_pair(
id, stamp));
345 poses.insert(std::make_pair(
id,
Transform(coordENU.x,coordENU.y,coordENU.z, roll,pitch,yaw)));
349 UERROR(
"Error parsing \"%s\" with St Lucia format (should have 12 values, e.g., 101215_153851_Ins0.log)", str.c_str());
355 if(strList.size() == 25)
369 stamps->insert(std::make_pair(
id, stamp));
375 Transform & previousPose = poses.at(
id-1);
376 yaw =
atan2(y-previousPose.
y(),x-previousPose.
x());
377 previousPose =
Transform(previousPose.x(), previousPose.y(),
yaw);
379 poses.insert(std::make_pair(
id,
Transform(x,y,z,0,0,yaw)));
383 UERROR(
"Error parsing \"%s\" with Malaga Urban format (should have 25 values, *_GPS.txt)", str.c_str());
389 if(strList.size() == 3)
402 stamps->insert(std::make_pair(
id, stamp));
408 Transform & previousPose = poses.at(
id-1);
409 yaw =
atan2(y-previousPose.
y(),x-previousPose.
x());
410 previousPose =
Transform(previousPose.x(), previousPose.y(),
yaw);
413 if(poses.size() == 0)
417 pose = originPose * pose;
418 poses.insert(std::make_pair(
id, pose));
422 UDEBUG(
"Not valid values detected: \"%s\"", str.c_str());
427 UERROR(
"Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)", str.c_str(), (int)strList.size());
430 else if(format == 1 || format==10 || format==11)
432 std::list<std::string> strList =
uSplit(str);
433 if((strList.size() == 8 && format!=11) || (strList.size() == 9 && format==11))
442 str =
uJoin(strList,
" ");
446 UWARN(
"Null transform read!? line parsed: \"%s\"", str.c_str());
452 stamps->insert(std::make_pair(
id, stamp));
467 poses.insert(std::make_pair(
id, pose));
472 UERROR(
"Error parsing \"%s\" with RGBD-SLAM format (should have 8 values (or 9 with id): stamp x y z qw qx qy qz [id])", str.c_str());
487 poses.insert(std::make_pair(
id, pose));
498 const std::string & filePath,
499 const std::map<int, GPS> & gpsValues,
502 UDEBUG(
"%s", filePath.c_str());
503 std::string tmpPath = filePath;
507 if(ext.compare(
"kml")!=0 && ext.compare(
"txt")!=0)
509 UERROR(
"Only txt and kml formats are supported!");
515 fopen_s(&fout, tmpPath.c_str(),
"w");
517 fout = fopen(tmpPath.c_str(),
"w");
521 if(ext.compare(
"kml")==0)
524 for(std::map<int, GPS>::const_iterator iter=gpsValues.begin(); iter!=gpsValues.end(); ++iter)
533 unsigned int abgr = 0xFF << 24 | (rgba & 0xFF) << 16 | (rgba & 0xFF00) | ((rgba >> 16) &0xFF);
535 std::string colorHexa =
uFormat(
"%08x", abgr);
537 fprintf(fout,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
538 fprintf(fout,
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
539 fprintf(fout,
"<Document>\n" 540 " <name>%s</name>\n", tmpPath.c_str());
541 fprintf(fout,
" <StyleMap id=\"msn_ylw-pushpin\">\n" 543 " <key>normal</key>\n" 544 " <styleUrl>#sn_ylw-pushpin</styleUrl>\n" 547 " <key>highlight</key>\n" 548 " <styleUrl>#sh_ylw-pushpin</styleUrl>\n" 551 " <Style id=\"sh_ylw-pushpin\">\n" 553 " <scale>1.2</scale>\n" 556 " <color>%s</color>\n" 559 " <Style id=\"sn_ylw-pushpin\">\n" 561 " <color>%s</color>\n" 563 " </Style>\n", colorHexa.c_str(), colorHexa.c_str());
564 fprintf(fout,
" <Placemark>\n" 566 " <styleUrl>#msn_ylw-pushpin</styleUrl>" 575 uSplit(tmpPath,
'.').front().c_str(),
580 fprintf(fout,
"# stamp longitude latitude altitude error bearing\n");
581 for(std::map<int, GPS>::const_iterator iter=gpsValues.begin(); iter!=gpsValues.end(); ++iter)
583 fprintf(fout,
"%f %.*f %.*f %.*f %.*f %.*f\n",
584 iter->second.stamp(),
585 8, iter->second.longitude(),
586 8, iter->second.latitude(),
587 8, iter->second.altitude(),
588 8, iter->second.error(),
589 8, iter->second.bearing());
600 float lengths[] = {100,200,300,400,500,600,700,800};
609 errors (
int32_t first_frame,
float r_err,
float t_err,
float len,
float speed) :
610 first_frame(first_frame),r_err(r_err),t_err(t_err),len(len),speed(speed) {}
614 std::vector<float>
dist;
616 for (
unsigned int i=1; i<poses.size(); i++) {
619 float dx = P1.
x()-P2.
x();
620 float dy = P1.
y()-P2.
y();
621 float dz = P1.
z()-P2.
z();
622 dist.push_back(dist[i-1]+
sqrt(dx*dx+dy*dy+dz*dz));
628 for (
unsigned int i=first_frame; i<dist.size(); i++)
629 if (dist[i]>dist[first_frame]+len)
635 float a = pose_error(0,0);
636 float b = pose_error(1,1);
637 float c = pose_error(2,2);
638 float d = 0.5*(a+b+c-1.0);
643 float dx = pose_error.
x();
644 float dy = pose_error.
y();
645 float dz = pose_error.
z();
646 return sqrt(dx*dx+dy*dy+dz*dz);
650 const std::vector<Transform> &poses_gt,
651 const std::vector<Transform> &poses_result,
655 UASSERT(poses_gt.size() == poses_result.size());
658 std::vector<errors> err;
673 float len = lengths[i];
690 float num_frames = (float)(last_frame-
first_frame+1);
691 float speed = len/(0.1*num_frames);
702 for (std::vector<errors>::iterator it=err.begin(); it!=err.end(); it++)
709 float num = err.size();
718 const std::vector<Transform> &poses_gt,
719 const std::vector<Transform> &poses_result,
723 UASSERT(poses_gt.size() == poses_result.size());
726 std::vector<errors> err;
729 for (
unsigned int i=0; i<poses_gt.size()-1; ++i)
735 float r_err = pose_error.
getAngle();
736 float t_err = pose_error.
getNorm();
739 err.push_back(
errors(i,r_err,t_err,0,0));
746 for (std::vector<errors>::iterator it=err.begin(); it!=err.end(); it++)
753 float num = err.size();
760 const std::map<int, Transform> & groundTruth,
761 const std::map<int, Transform> & poses,
762 float & translational_rmse,
763 float & translational_mean,
764 float & translational_median,
765 float & translational_std,
766 float & translational_min,
767 float & translational_max,
768 float & rotational_rmse,
769 float & rotational_mean,
770 float & rotational_median,
771 float & rotational_std,
772 float & rotational_min,
773 float & rotational_max)
776 translational_rmse = 0.0f;
777 translational_mean = 0.0f;
778 translational_median = 0.0f;
779 translational_std = 0.0f;
780 translational_min = 0.0f;
781 translational_max = 0.0f;
783 rotational_rmse = 0.0f;
784 rotational_mean = 0.0f;
785 rotational_median = 0.0f;
786 rotational_std = 0.0f;
787 rotational_min = 0.0f;
788 rotational_max = 0.0f;
791 pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
792 cloud1.resize(poses.size());
793 cloud2.resize(poses.size());
796 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
798 std::map<int, Transform>::const_iterator jter=groundTruth.find(iter->first);
799 if(jter != groundTruth.end())
803 idFirst = iter->first;
805 cloud1[oi] = pcl::PointXYZ(jter->second.x(), jter->second.y(), jter->second.z());
806 cloud2[oi++] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
820 t = groundTruth.at(idFirst) * poses.at(idFirst).inverse();
823 std::vector<float> translationalErrors(poses.size());
824 std::vector<float> rotationalErrors(poses.size());
825 float sumTranslationalErrors = 0.0f;
826 float sumRotationalErrors = 0.0f;
827 float sumSqrdTranslationalErrors = 0.0f;
828 float sumSqrdRotationalErrors = 0.0f;
829 float radToDegree = 180.0f /
M_PI;
831 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
833 std::map<int, Transform>::const_iterator jter = groundTruth.find(iter->first);
834 if(jter!=groundTruth.end())
837 Eigen::Vector3f xAxis(1,0,0);
838 Eigen::Vector3f vA = pose.
toEigen3f().linear()*xAxis;
839 Eigen::Vector3f vB = jter->second.toEigen3f().linear()*xAxis;
840 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
841 rotationalErrors[oi] = a*radToDegree;
842 translationalErrors[oi] = pose.
getDistance(jter->second);
844 sumTranslationalErrors+=translationalErrors[oi];
845 sumSqrdTranslationalErrors+=translationalErrors[oi]*translationalErrors[oi];
846 sumRotationalErrors+=rotationalErrors[oi];
847 sumSqrdRotationalErrors+=rotationalErrors[oi]*rotationalErrors[oi];
851 translational_min = translational_max = translationalErrors[oi];
852 rotational_min = rotational_max = rotationalErrors[oi];
856 if(translationalErrors[oi] < translational_min)
858 translational_min = translationalErrors[oi];
860 else if(translationalErrors[oi] > translational_max)
862 translational_max = translationalErrors[oi];
865 if(rotationalErrors[oi] < rotational_min)
867 rotational_min = rotationalErrors[oi];
869 else if(rotationalErrors[oi] > rotational_max)
871 rotational_max = rotationalErrors[oi];
878 translationalErrors.resize(oi);
879 rotationalErrors.resize(oi);
882 float total = float(oi);
883 translational_rmse =
std::sqrt(sumSqrdTranslationalErrors/total);
884 translational_mean = sumTranslationalErrors/total;
885 translational_median = translationalErrors[oi/2];
888 rotational_rmse =
std::sqrt(sumSqrdRotationalErrors/total);
889 rotational_mean = sumRotationalErrors/total;
890 rotational_median = rotationalErrors[oi/2];
897 const std::map<int, Transform> & poses,
898 const std::multimap<int, Link> & links,
899 float & maxLinearErrorRatio,
900 float & maxAngularErrorRatio,
901 float & maxLinearError,
902 float & maxAngularError,
903 const Link ** maxLinearErrorLink,
904 const Link ** maxAngularErrorLink,
907 maxLinearErrorRatio = -1;
908 maxAngularErrorRatio = -1;
910 maxAngularError = -1;
912 UDEBUG(
"poses=%d links=%d", (
int)poses.size(), (int)links.size());
913 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
916 if(iter->second.transVariance() <= 1.0 && iter->second.from() != iter->second.to() && iter->second.type() !=
Link::kLandmark)
922 float linearError =
uMax3(
923 fabs(iter->second.transform().x() - t.x()),
924 fabs(iter->second.transform().y() - t.y()),
925 for3DoF?0:fabs(iter->second.transform().z() - t.z()));
926 UASSERT(iter->second.transVariance(
false)>0.0);
927 float stddevLinear =
sqrt(iter->second.transVariance(
false));
928 float linearErrorRatio = linearError/stddevLinear;
929 if(linearErrorRatio > maxLinearErrorRatio)
931 maxLinearError = linearError;
932 maxLinearErrorRatio = linearErrorRatio;
933 if(maxLinearErrorLink)
935 *maxLinearErrorLink = &iter->second;
939 float opt_roll,opt_pitch,opt_yaw;
940 float link_roll,link_pitch,link_yaw;
941 t.getEulerAngles(opt_roll, opt_pitch, opt_yaw);
943 float angularError =
uMax3(
944 for3DoF?0:fabs(opt_roll - link_roll),
945 for3DoF?0:fabs(opt_pitch - link_pitch),
946 fabs(opt_yaw - link_yaw));
947 angularError = angularError>
M_PI?2*
M_PI-angularError:angularError;
948 UASSERT(iter->second.rotVariance(
false)>0.0);
949 float stddevAngular =
sqrt(iter->second.rotVariance(
false));
950 float angularErrorRatio = angularError/stddevAngular;
951 if(angularErrorRatio > maxAngularErrorRatio)
953 maxAngularError = angularError;
954 maxAngularErrorRatio = angularErrorRatio;
955 if(maxAngularErrorLink)
957 *maxAngularErrorLink = &iter->second;
966 std::vector<double> maxOdomInf(6,0.0);
967 maxOdomInf.resize(6,0.0);
968 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
972 for(
int i=0; i<6; ++i)
974 const double & v = iter->second.infMatrix().at<
double>(i,i);
975 if(maxOdomInf[i] < v)
982 if(maxOdomInf[0] == 0.0)
993 std::multimap<int, Link> & links,
999 std::multimap<int, Link>::iterator iter = links.find(from);
1000 while(iter != links.end() && iter->first == from)
1002 if(iter->second.to() == to && (type==
Link::kUndef || type == iter->second.type()))
1012 iter = links.find(to);
1013 while(iter != links.end() && iter->first == to)
1015 if(iter->second.to() == from && (type==
Link::kUndef || type == iter->second.type()))
1026 std::multimap<int, int> & links,
1031 std::multimap<int, int>::iterator iter = links.find(from);
1032 while(iter != links.end() && iter->first == from)
1034 if(iter->second == to)
1044 iter = links.find(to);
1045 while(iter != links.end() && iter->first == to)
1047 if(iter->second == from)
1057 const std::multimap<int, Link> & links,
1063 std::multimap<int, Link>::const_iterator iter = links.find(from);
1064 while(iter != links.end() && iter->first == from)
1066 if(iter->second.to() == to && (type==
Link::kUndef || type == iter->second.type()))
1076 iter = links.find(to);
1077 while(iter != links.end() && iter->first == to)
1079 if(iter->second.to() == from && (type==
Link::kUndef || type == iter->second.type()))
1090 const std::multimap<int, int> & links,
1095 std::multimap<int, int>::const_iterator iter = links.find(from);
1096 while(iter != links.end() && iter->first == from)
1098 if(iter->second == to)
1108 iter = links.find(to);
1109 while(iter != links.end() && iter->first == to)
1111 if(iter->second == from)
1122 const std::multimap<int, Link> & links,
1125 std::list<Link> output;
1126 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter != links.end(); ++iter)
1128 if(iter->second.from() == from)
1130 output.push_back(iter->second);
1132 else if(iter->second.to() == from)
1134 output.push_back(iter->second.inverse());
1141 const std::multimap<int, Link> & links)
1143 std::multimap<int, Link> output;
1144 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
1146 if(
graph::findLink(output, iter->second.from(), iter->second.to(),
true, iter->second.type()) == output.end())
1148 output.insert(*iter);
1155 const std::multimap<int, Link> & links,
1159 std::multimap<int, Link> output;
1160 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
1164 if((!inverted && iter->second.from() != iter->second.to())||
1165 (inverted && iter->second.from() == iter->second.to()))
1167 output.insert(*iter);
1170 else if((!inverted && iter->second.type() != filteredType)||
1171 (inverted && iter->second.type() == filteredType))
1173 output.insert(*iter);
1180 const std::map<int, Link> & links,
1184 std::map<int, Link> output;
1185 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
1189 if((!inverted && iter->second.from() != iter->second.to())||
1190 (inverted && iter->second.from() == iter->second.to()))
1192 output.insert(*iter);
1195 else if((!inverted && iter->second.type() != filteredType)||
1196 (inverted && iter->second.type() == filteredType))
1198 output.insert(*iter);
1205 const std::map<int, Transform> & poses,
1207 float horizontalFOV,
1209 float nearClipPlaneDistance,
1210 float farClipPlaneDistance,
1213 std::map<int, Transform> output;
1217 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1218 std::vector<int> ids(poses.size());
1220 cloud->resize(poses.size());
1221 ids.resize(poses.size());
1223 for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
1225 if(!iter->second.isNull())
1227 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1228 ids[oi++] = iter->first;
1236 pcl::IndicesPtr(
new std::vector<int>),
1240 nearClipPlaneDistance,
1241 farClipPlaneDistance,
1245 for(
unsigned int i=0; i<indices->size(); ++i)
1247 output.insert(*poses.find(ids[indices->at(i)]));
1254 const std::map<int, Transform> & poses,
1259 if(poses.size() > 2 && radius > 0.0f)
1261 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1262 cloud->resize(poses.size());
1264 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter, ++i)
1266 (*cloud)[i] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1271 std::vector<int> names =
uKeys(poses);
1272 std::vector<Transform> transforms =
uValues(poses);
1274 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1275 tree->setInputCloud(cloud);
1276 std::set<int> indicesChecked;
1277 std::set<int> indicesKept;
1279 for(
unsigned int i=0; i<cloud->size(); ++i)
1281 if(indicesChecked.find(i) == indicesChecked.end())
1284 std::vector<float> kDistances;
1285 tree->radiusSearch(cloud->at(i), radius,
kIndices, kDistances);
1287 std::set<int> cloudIndices;
1288 const Transform & currentT = transforms.at(i);
1289 Eigen::Vector3f vA = currentT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1290 for(
unsigned int j=0; j<kIndices.size(); ++j)
1292 if(indicesChecked.find(kIndices[j]) == indicesChecked.end())
1296 const Transform & checkT = transforms.at(kIndices[j]);
1298 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1299 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
1302 cloudIndices.insert(kIndices[j]);
1307 cloudIndices.insert(kIndices[j]);
1314 bool lastAdded =
false;
1315 for(std::set<int>::reverse_iterator iter = cloudIndices.rbegin(); iter!=cloudIndices.rend(); ++iter)
1319 indicesKept.insert(*iter);
1322 indicesChecked.insert(*iter);
1327 bool firstAdded =
false;
1328 for(std::set<int>::iterator iter = cloudIndices.begin(); iter!=cloudIndices.end(); ++iter)
1332 indicesKept.insert(*iter);
1335 indicesChecked.insert(*iter);
1343 UINFO(
"Cloud filtered In = %d, Out = %d (radius=%f angle=%f keepLatest=%d)", cloud->size(), indicesKept.size(), radius,
angle, keepLatest?1:0);
1347 std::map<int, Transform> keptPoses;
1348 for(std::set<int>::iterator iter = indicesKept.begin(); iter!=indicesKept.end(); ++iter)
1350 keptPoses.insert(std::make_pair(names.at(*iter), transforms.at(*iter)));
1354 keptPoses.insert(*poses.begin());
1355 keptPoses.insert(*poses.rbegin());
1367 std::multimap<int, int> clusters;
1368 if(poses.size() > 1 && radius > 0.0f)
1370 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1371 cloud->resize(poses.size());
1373 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter, ++i)
1375 (*cloud)[i] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1380 std::vector<int> ids =
uKeys(poses);
1381 std::vector<Transform> transforms =
uValues(poses);
1383 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1384 tree->setInputCloud(cloud);
1386 for(
unsigned int i=0; i<cloud->size(); ++i)
1389 std::vector<float> kDistances;
1390 tree->radiusSearch(cloud->at(i), radius,
kIndices, kDistances);
1392 std::set<int> cloudIndices;
1393 const Transform & currentT = transforms.at(i);
1394 Eigen::Vector3f vA = currentT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1395 for(
unsigned int j=0; j<kIndices.size(); ++j)
1397 if((
int)i != kIndices[j])
1401 const Transform & checkT = transforms.at(kIndices[j]);
1403 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1404 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
1407 clusters.insert(std::make_pair(ids[i], ids[kIndices[j]]));
1412 clusters.insert(std::make_pair(ids[i], ids[kIndices[j]]));
1422 const std::map<int, Transform> & poses,
1423 const std::multimap<int, Link> & links,
1424 std::multimap<int, int> & hyperNodes,
1425 std::multimap<int, Link> & hyperLinks)
1427 UINFO(
"Input: poses=%d links=%d", (
int)poses.size(), (int)links.size());
1429 std::map<int, int> posesToHyperNodes;
1430 std::map<int, std::multimap<int, Link> > clusterloopClosureLinks;
1433 std::multimap<int, Link> bidirectionalLoopClosureLinks;
1434 for(std::multimap<int, Link>::const_iterator jter=links.begin(); jter!=links.end(); ++jter)
1438 jter->second.userDataCompressed().empty())
1440 if(
uContains(poses, jter->second.from()) &&
1443 UASSERT_MSG(
graph::findLink(links, jter->second.to(), jter->second.from(),
false) == links.end(),
"Input links should be unique!");
1444 bidirectionalLoopClosureLinks.insert(std::make_pair(jter->second.from(), jter->second));
1450 UINFO(
"Clustering hyper nodes...");
1452 for(std::map<int, Transform>::const_reverse_iterator iter=poses.rbegin(); iter!=poses.rend(); ++iter)
1454 if(posesToHyperNodes.find(iter->first) == posesToHyperNodes.end())
1456 int hyperNodeId = iter->first;
1457 std::list<int> loopClosures;
1458 std::set<int> loopClosuresAdded;
1459 loopClosures.push_back(iter->first);
1460 std::multimap<int, Link> clusterLinks;
1461 while(loopClosures.size())
1463 int id = loopClosures.front();
1464 loopClosures.pop_front();
1466 UASSERT(posesToHyperNodes.find(
id) == posesToHyperNodes.end());
1468 posesToHyperNodes.insert(std::make_pair(
id, hyperNodeId));
1469 hyperNodes.insert(std::make_pair(hyperNodeId,
id));
1471 for(std::multimap<int, Link>::const_iterator jter=bidirectionalLoopClosureLinks.find(
id); jter!=bidirectionalLoopClosureLinks.end() && jter->first==id; ++jter)
1473 if(posesToHyperNodes.find(jter->second.to()) == posesToHyperNodes.end() &&
1474 loopClosuresAdded.find(jter->second.to()) == loopClosuresAdded.end())
1476 loopClosures.push_back(jter->second.to());
1477 loopClosuresAdded.insert(jter->second.to());
1478 clusterLinks.insert(*jter);
1479 clusterLinks.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
1480 if(jter->second.from() < jter->second.to())
1482 UWARN(
"Child to Parent link? %d->%d (type=%d)",
1483 jter->second.from(),
1485 jter->second.type());
1490 UASSERT(clusterloopClosureLinks.find(hyperNodeId) == clusterloopClosureLinks.end());
1491 clusterloopClosureLinks.insert(std::make_pair(hyperNodeId, clusterLinks));
1492 UDEBUG(
"Created hyper node %d with %d children (%f%%)",
1493 hyperNodeId, (
int)loopClosuresAdded.size(), float(posesToHyperNodes.size())/
float(poses.size())*100.0
f);
1496 UINFO(
"Clustering hyper nodes... done! (%f s)", timer.ticks());
1499 UINFO(
"Creating hyper links...");
1501 for(std::multimap<int, Link>::const_reverse_iterator jter=links.rbegin(); jter!=links.rend(); ++jter)
1505 !jter->second.userDataCompressed().empty()) &&
1506 uContains(poses, jter->second.from()) &&
1509 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.from()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1510 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.to()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1511 int hyperNodeIDFrom = posesToHyperNodes.at(jter->second.from());
1512 int hyperNodeIDTo = posesToHyperNodes.at(jter->second.to());
1515 if(hyperNodeIDFrom != hyperNodeIDTo)
1517 std::multimap<int, Link>::iterator tmpIter =
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo);
1518 if(tmpIter!=hyperLinks.end() &&
1519 hyperNodeIDFrom == jter->second.from() &&
1520 hyperNodeIDTo == jter->second.to() &&
1525 hyperLinks.erase(tmpIter);
1529 if(
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo) == hyperLinks.end())
1531 UASSERT(clusterloopClosureLinks.find(hyperNodeIDFrom) != clusterloopClosureLinks.end());
1532 UASSERT(clusterloopClosureLinks.find(hyperNodeIDTo) != clusterloopClosureLinks.end());
1533 std::multimap<int, Link> tmpLinks = clusterloopClosureLinks.at(hyperNodeIDFrom);
1534 tmpLinks.insert(clusterloopClosureLinks.at(hyperNodeIDTo).begin(), clusterloopClosureLinks.at(hyperNodeIDTo).end());
1535 tmpLinks.insert(std::make_pair(jter->second.from(), jter->second));
1537 std::list<int> path =
computePath(tmpLinks, hyperNodeIDFrom, hyperNodeIDTo,
false,
true);
1539 uFormat(
"path.size()=%d, hyperNodeIDFrom=%d, hyperNodeIDTo=%d",
1542 hyperNodeIDTo).c_str());
1544 if(path.size() > 10)
1546 UWARN(
"Large path! %d nodes", (
int)path.size());
1547 std::stringstream stream;
1548 for(std::list<int>::const_iterator iter=path.begin(); iter!=path.end();++iter)
1550 if(iter!=path.begin())
1557 UWARN(
"Path = [%s]", stream.str().c_str());
1561 std::list<int>::iterator iter=path.begin();
1565 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1566 UASSERT(foundIter != tmpLinks.end());
1567 Link hyperLink = foundIter->second;
1570 for(; iter!=path.end(); ++iter)
1573 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1574 UASSERT(foundIter != tmpLinks.end());
1575 hyperLink = hyperLink.merge(foundIter->second, jter->second.type());
1580 UASSERT(hyperLink.from() == hyperNodeIDFrom);
1581 UASSERT(hyperLink.to() == hyperNodeIDTo);
1582 hyperLinks.insert(std::make_pair(hyperNodeIDFrom, hyperLink));
1584 UDEBUG(
"Created hyper link %d->%d (%f%%)",
1585 hyperLink.from(), hyperLink.to(), float(i)/float(links.size())*100.0
f);
1586 if(hyperLink.transform().getNorm() > jter->second.transform().getNorm()+1)
1588 UWARN(
"Large hyper link %d->%d (%f m)! original %d->%d (%f m)",
1591 hyperLink.transform().getNorm(),
1592 jter->second.from(),
1594 jter->second.transform().getNorm());
1602 UINFO(
"Creating hyper links... done! (%f s)", timer.ticks());
1604 UINFO(
"Output: poses=%d links=%d", (
int)
uUniqueKeys(hyperNodes).size(), (
int)links.size());
1620 int id()
const {
return id_;}
1630 return pose_.getDistance(pose);
1648 typedef std::pair<int, float>
Pair;
1653 return a.second > b.second;
1659 const std::map<int, rtabmap::Transform> & poses,
1660 const std::multimap<int, int> & links,
1663 bool updateNewCosts)
1665 std::list<std::pair<int, Transform> > path;
1667 int startNode = from;
1670 std::map<int, Node> nodes;
1671 nodes.insert(std::make_pair(startNode,
Node(startNode, 0, poses.at(startNode))));
1672 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1673 std::multimap<float, int> pqmap;
1676 pqmap.insert(std::make_pair(0, startNode));
1680 pq.push(
Pair(startNode, 0));
1683 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1688 currentNode = &nodes.find(pqmap.begin()->second)->second;
1689 pqmap.erase(pqmap.begin());
1693 currentNode = &nodes.find(pq.top().first)->second;
1699 if(currentNode->
id() == endNode)
1701 while(currentNode->
id()!=startNode)
1703 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
1704 currentNode = &nodes.find(currentNode->
fromId())->second;
1706 path.push_front(std::make_pair(startNode, poses.at(startNode)));
1711 for(std::multimap<int, int>::const_iterator iter = links.find(currentNode->
id());
1712 iter!=links.end() && iter->first == currentNode->
id();
1715 std::map<int, Node>::iterator nodeIter = nodes.find(iter->second);
1716 if(nodeIter == nodes.end())
1718 std::map<int, rtabmap::Transform>::const_iterator poseIter = poses.find(iter->second);
1719 if(poseIter == poses.end())
1721 UERROR(
"Next pose %d (from %d) should be found in poses! Ignoring it!", iter->second, iter->first);
1725 Node n(iter->second, currentNode->
id(), poseIter->second);
1727 n.setDistToEnd(n.distFrom(endPose));
1729 nodes.insert(std::make_pair(iter->second, n));
1732 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
1736 pq.push(
Pair(n.id(), n.totalCost()));
1740 else if(updateNewCosts && nodeIter->second.isOpened())
1742 float newCostSoFar = currentNode->
costSoFar() + currentNode->
distFrom(nodeIter->second.pose());
1743 if(nodeIter->second.costSoFar() > newCostSoFar)
1746 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1748 if(mapIter->second == nodeIter->first)
1750 pqmap.erase(mapIter);
1751 nodeIter->second.setCostSoFar(newCostSoFar);
1752 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1765 const std::multimap<int, Link> & links,
1768 bool updateNewCosts,
1769 bool useSameCostForAllLinks)
1771 std::list<int> path;
1773 int startNode = from;
1775 std::map<int, Node> nodes;
1776 nodes.insert(std::make_pair(startNode,
Node(startNode, 0,
Transform())));
1777 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1778 std::multimap<float, int> pqmap;
1781 pqmap.insert(std::make_pair(0, startNode));
1785 pq.push(
Pair(startNode, 0));
1788 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1793 currentNode = &nodes.find(pqmap.begin()->second)->second;
1794 pqmap.erase(pqmap.begin());
1798 currentNode = &nodes.find(pq.top().first)->second;
1804 if(currentNode->
id() == endNode)
1806 while(currentNode->
id()!=startNode)
1808 path.push_front(currentNode->
id());
1809 currentNode = &nodes.find(currentNode->
fromId())->second;
1811 path.push_front(startNode);
1816 for(std::multimap<int, Link>::const_iterator iter = links.find(currentNode->
id());
1817 iter!=links.end() && iter->first == currentNode->
id();
1820 std::map<int, Node>::iterator nodeIter = nodes.find(iter->second.to());
1822 if(!useSameCostForAllLinks)
1824 cost = iter->second.transform().getNorm();
1826 if(nodeIter == nodes.end())
1831 nodes.insert(std::make_pair(iter->second.to(), n));
1834 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
1838 pq.push(
Pair(n.id(), n.totalCost()));
1841 else if(!useSameCostForAllLinks && updateNewCosts && nodeIter->second.isOpened())
1843 float newCostSoFar = currentNode->
costSoFar() + cost;
1844 if(nodeIter->second.costSoFar() > newCostSoFar)
1847 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1849 if(mapIter->second == nodeIter->first)
1851 pqmap.erase(mapIter);
1852 nodeIter->second.setCostSoFar(newCostSoFar);
1853 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1870 bool lookInDatabase,
1871 bool updateNewCosts,
1872 float linearVelocity,
1873 float angularVelocity)
1878 std::list<std::pair<int, Transform> > path;
1879 UDEBUG(
"fromId=%d, toId=%d, lookInDatabase=%d, updateNewCosts=%d, linearVelocity=%f, angularVelocity=%f",
1887 std::multimap<int, Link> allLinks;
1892 allLinks = memory->
getAllLinks(lookInDatabase,
true,
true);
1893 for(std::multimap<int, Link>::iterator iter=allLinks.begin(); iter!=allLinks.end(); ++iter)
1895 if(iter->second.to() < 0)
1897 allLinks.insert(std::make_pair(iter->second.to(), iter->second.inverse()));
1900 UINFO(
"getting all %d links time = %f s", (
int)allLinks.size(), t.
ticks());
1904 int startNode = fromId;
1906 std::map<int, Node> nodes;
1908 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1909 std::multimap<float, int> pqmap;
1912 pqmap.insert(std::make_pair(0, startNode));
1916 pq.push(
Pair(startNode, 0));
1919 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1924 currentNode = &nodes.find(pqmap.begin()->second)->second;
1925 pqmap.erase(pqmap.begin());
1929 currentNode = &nodes.find(pq.top().first)->second;
1935 if(currentNode->
id() == endNode)
1937 while(currentNode->
id()!=startNode)
1939 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
1940 currentNode = &nodes.find(currentNode->
fromId())->second;
1942 path.push_front(std::make_pair(startNode, currentNode->
pose()));
1947 std::multimap<int, Link> links;
1948 if(allLinks.size() == 0)
1950 links = memory->
getLinks(currentNode->
id(), lookInDatabase,
true);
1954 for(std::multimap<int, Link>::const_iterator iter = allLinks.lower_bound(currentNode->
id());
1955 iter!=allLinks.end() && iter->first == currentNode->
id();
1958 links.insert(std::make_pair(iter->second.to(), iter->second));
1961 for(std::multimap<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
1963 if(iter->second.from() != iter->second.to())
1965 Transform nextPose = currentNode->
pose()*iter->second.transform();
1967 if(linearVelocity <= 0.0
f && angularVelocity <= 0.0
f)
1970 cost = iter->second.transform().
getNorm();
1974 if(linearVelocity > 0.0
f)
1976 cost += iter->second.transform().getNorm()/linearVelocity;
1978 if(angularVelocity > 0.0
f)
1980 Eigen::Vector4f v1 = Eigen::Vector4f(nextPose.
x()-currentNode->
pose().
x(), nextPose.
y()-currentNode->
pose().
y(), nextPose.
z()-currentNode->
pose().
z(), 1.0f);
1982 float angle = pcl::getAngle3D(v1, v2);
1983 cost += angle / angularVelocity;
1987 std::map<int, Node>::iterator nodeIter = nodes.find(iter->first);
1988 if(nodeIter == nodes.end())
1990 Node n(iter->second.to(), currentNode->
id(), nextPose);
1993 nodes.insert(std::make_pair(iter->second.to(), n));
1996 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
2000 pq.push(
Pair(n.id(), n.totalCost()));
2003 else if(updateNewCosts && nodeIter->second.isOpened())
2005 float newCostSoFar = currentNode->
costSoFar() + cost;
2006 if(nodeIter->second.costSoFar() > newCostSoFar)
2009 nodeIter->second.setPose(nextPose);
2012 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
2014 if(mapIter->second == nodeIter->first)
2016 pqmap.erase(mapIter);
2017 nodeIter->second.setCostSoFar(newCostSoFar);
2018 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
2031 std::stringstream stream;
2033 std::list<std::pair<int, Transform> >::const_iterator previousIter = path.end();
2035 for(std::list<std::pair<int, Transform> >::const_iterator iter=path.begin(); iter!=path.end();++iter)
2037 if(iter!=path.begin())
2042 if(previousIter!=path.end())
2047 std::multimap<int, Link>::iterator jter =
graph::findLink(allLinks, previousIter->first, iter->first);
2048 if(jter != allLinks.end())
2058 ++linkTypes[jter->second.type()];
2059 stream <<
"[" << jter->second.type() <<
"]";
2060 length += jter->second.transform().getNorm();
2065 stream << iter->first;
2069 UDEBUG(
"Path (%f m) = [%s]", length, stream.str().c_str());
2070 std::stringstream streamB;
2071 for(
unsigned int i=0; i<linkTypes.size(); ++i)
2077 streamB << i <<
"=" << linkTypes[i];
2079 UDEBUG(
"Link types = %s", streamB.str().c_str());
2086 const std::map<int, rtabmap::Transform> & poses,
2091 std::map<int, float> nearestNodes =
findNearestNodes(targetPose, poses, 0, 0, 1);
2092 if(!nearestNodes.empty())
2094 id = nearestNodes.begin()->first;
2097 *distance = nearestNodes.begin()->second;
2106 const std::map<int, Transform> & poses,
2113 std::map<int, Transform> nodesMinusTarget = poses;
2114 Transform targetPose = poses.at(nodeId);
2115 nodesMinusTarget.erase(nodeId);
2122 const std::map<int, Transform> & poses,
2130 std::map<int, float> foundNodes;
2136 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
2137 cloud->resize(poses.size());
2138 std::vector<int> ids(poses.size());
2140 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter)
2142 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
2144 ids[oi] = iter->first;
2152 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
2153 kdTree->setInputCloud(cloud);
2154 std::vector<int> ind;
2155 std::vector<float> sqrdDist;
2156 pcl::PointXYZ pt(targetPose.
x(), targetPose.
y(), targetPose.
z());
2159 kdTree->radiusSearch(pt, radius, ind, sqrdDist, k);
2163 kdTree->nearestKSearch(pt, k, ind, sqrdDist);
2165 Eigen::Vector3f vA = targetPose.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
2166 for(
unsigned int i=0; i<ind.size(); ++i)
2172 const Transform & checkT = poses.at(ids[ind[i]]);
2174 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
2175 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
2178 foundNodes.insert(std::make_pair(ids[ind[i]], sqrdDist[i]));
2183 foundNodes.insert(std::make_pair(ids[ind[i]], sqrdDist[i]));
2188 UDEBUG(
"found nodes=%d", (
int)foundNodes.size());
2195 const std::map<int, Transform> & poses,
2202 std::map<int, Transform> nodesMinusTarget = poses;
2203 Transform targetPose = poses.at(nodeId);
2204 nodesMinusTarget.erase(nodeId);
2210 const std::map<int, Transform> & poses,
2215 std::map<int, float> nearestNodes =
findNearestNodes(targetPose, poses, radius, angle, k);
2216 std::map<int, Transform> foundPoses;
2217 for(std::map<int, float>::iterator iter=nearestNodes.begin(); iter!=nearestNodes.end(); ++iter)
2219 foundPoses.insert(*poses.find(iter->first));
2221 UDEBUG(
"found nodes=%d", (
int)foundPoses.size());
2230 std::map<int, float>
getNodesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius)
2238 std::map<int, Transform>
getPosesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius,
float angle)
2249 const std::vector<std::pair<int, Transform> > & path,
2250 unsigned int fromIndex,
2251 unsigned int toIndex)
2256 UASSERT(fromIndex < path.size() && toIndex < path.size() && fromIndex <= toIndex);
2257 if(fromIndex >= toIndex)
2259 toIndex = (
unsigned int)path.size()-1;
2261 float x=0, y=0, z=0;
2262 for(
unsigned int i=fromIndex; i<toIndex-1; ++i)
2264 x += fabs(path[i].second.x() - path[i+1].second.x());
2265 y += fabs(path[i].second.y() - path[i+1].second.y());
2266 z += fabs(path[i].second.z() - path[i+1].second.z());
2268 length =
sqrt(x*x + y*y + z*z);
2274 const std::map<int, Transform> & path)
2279 float x=0, y=0, z=0;
2280 std::map<int, Transform>::const_iterator iter=path.begin();
2283 for(; iter!=path.end(); ++iter)
2285 const Transform & currentPose = iter->second;
2286 x += fabs(previousPose.
x() - currentPose.
x());
2287 y += fabs(previousPose.
y() - currentPose.
y());
2288 z += fabs(previousPose.
z() - currentPose.
z());
2289 previousPose = currentPose;
2291 length =
sqrt(x*x + y*y + z*z);
2298 std::map<int, Transform> poses,
2299 const std::multimap<int, Link> & links)
2301 std::list<std::map<int, Transform> > paths;
2302 if(poses.size() && links.size())
2307 std::map<int, Transform> path;
2308 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end();)
2310 std::multimap<int, Link>::const_iterator jter =
findLink(links, path.rbegin()->first, iter->first);
2314 poses.erase(iter++);
2322 paths.push_back(path);
2335 min[0] = max[0] = poses.begin()->second.x();
2336 min[1] = max[1] = poses.begin()->second.y();
2337 min[2] = max[2] = poses.begin()->second.z();
2338 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
2340 if(min[0] > iter->second.x())
2341 min[0] = iter->second.x();
2342 if(max[0] < iter->second.x())
2343 max[0] = iter->second.x();
2344 if(min[1] > iter->second.y())
2345 min[1] = iter->second.y();
2346 if(max[1] < iter->second.y())
2347 max[1] = iter->second.y();
2348 if(min[2] > iter->second.z())
2349 min[2] = iter->second.z();
2350 if(max[2] < iter->second.z())
2351 max[2] = iter->second.z();
int UTILITE_EXP uStr2Int(const std::string &str)
float distFrom(const rtabmap::Transform &pose) const
std::list< K > uUniqueKeys(const std::multimap< K, V > &mm)
GLM_FUNC_DECL T roll(detail::tquat< T, P > const &x)
T uVariance(const T *v, unsigned int size, T meanV)
bool RTABMAP_EXP isFinite(const cv::Point3f &pt)
void setPose(const Transform &pose)
std::list< Link > RTABMAP_EXP findLinks(const std::multimap< int, Link > &links, int from)
Transform RTABMAP_EXP transformFromXYZCorrespondencesSVD(const pcl::PointCloud< pcl::PointXYZ > &cloud1, const pcl::PointCloud< pcl::PointXYZ > &cloud2)
bool saveGraph(const std::string &fileName, const std::map< int, Transform > &poses, const std::multimap< int, Link > &edgeConstraints)
float rotationError(const Transform &pose_error)
void reduceGraph(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, std::multimap< int, int > &hyperNodes, std::multimap< int, Link > &hyperLinks)
std::map< int, Transform > RTABMAP_EXP radiusPosesFiltering(const std::map< int, Transform > &poses, float radius, float angle, bool keepLatest=true)
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true, Link::Type type=Link::kUndef)
void RTABMAP_EXP computeMaxGraphErrors(const std::map< int, Transform > &poses, const std::multimap< int, Link > &links, float &maxLinearErrorRatio, float &maxAngularErrorRatio, float &maxLinearError, float &maxAngularError, const Link **maxLinearErrorLink=0, const Link **maxAngularErrorLink=0, bool for3DoF=false)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
std::vector< K > uKeys(const std::multimap< K, V > &mm)
double UTILITE_EXP uStr2Double(const std::string &str)
rtabmap::Transform pose() const
bool RTABMAP_EXP exportGPS(const std::string &filePath, const std::map< int, GPS > &gpsValues, unsigned int rgba=0xFFFFFFFF)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
float translationError(const Transform &pose_error)
int RTABMAP_EXP findNearestNode(const std::map< int, rtabmap::Transform > &poses, const rtabmap::Transform &targetPose, float *distance=0)
float UTILITE_EXP uStr2Float(const std::string &str)
std::map< std::string, std::string > ParametersMap
GLM_FUNC_DECL genType::value_type distance(genType const &p0, genType const &p1)
std::multimap< int, Link > RTABMAP_EXP filterLinks(const std::multimap< int, Link > &links, Link::Type filteredType, bool inverted=false)
Basic mathematics functions.
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
Some conversion functions.
std::string getExtension()
GLM_FUNC_DECL T pitch(detail::tquat< T, P > const &x)
std::vector< float > trajectoryDistances(const std::vector< Transform > &poses)
std::multimap< int, Link > RTABMAP_EXP filterDuplicateLinks(const std::multimap< int, Link > &links)
void setDistToEnd(float distToEnd)
pcl::IndicesPtr RTABMAP_EXP frustumFiltering(const pcl::PointCloud< pcl::PointXYZ >::Ptr &cloud, const pcl::IndicesPtr &indices, const Transform &cameraPose, float horizontalFOV, float verticalFOV, float nearClipPlaneDistance, float farClipPlaneDistance, bool negative=false)
#define UASSERT(condition)
Wrappers of STL for convenient functions.
std::list< std::string > uSplit(const std::string &str, char separator=' ')
std::string uJoin(const std::list< std::string > &strings, const std::string &separator="")
T uMax3(const T &a, const T &b, const T &c)
cv::Point3d toENU_WGS84(const GeodeticCoords &origin) const
Node(int id, int fromId, const rtabmap::Transform &pose)
#define UASSERT_MSG(condition, msg_str)
std::map< int, float > getNodesInRadius(int nodeId, const std::map< int, Transform > &nodes, float radius)
Transform RTABMAP_EXP calcRMSE(const std::map< int, Transform > &groundTruth, const std::map< int, Transform > &poses, float &translational_rmse, float &translational_mean, float &translational_median, float &translational_std, float &translational_min, float &translational_max, float &rotational_rmse, float &rotational_mean, float &rotational_median, float &rotational_std, float &rotational_min, float &rotational_max)
std::vector< double > RTABMAP_EXP getMaxOdomInf(const std::multimap< int, Link > &links)
std::map< int, Transform > getPosesInRadius(int nodeId, const std::map< int, Transform > &nodes, float radius, float angle)
void setClosed(bool closed)
std::string UTILITE_EXP uReplaceChar(const std::string &str, char before, char after)
std::list< std::pair< int, Transform > > RTABMAP_EXP computePath(const std::map< int, rtabmap::Transform > &poses, const std::multimap< int, int > &links, int from, int to, bool updateNewCosts=false)
static ULogger::Level level()
bool uIsNumber(const std::string &str)
GLM_FUNC_QUALIFIER T atan2(T x, T y)
Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what q...
bool uContains(const std::list< V > &list, const V &value)
std::multimap< int, int > RTABMAP_EXP radiusPosesClustering(const std::map< int, Transform > &poses, float radius, float angle)
bool RTABMAP_EXP exportPoses(const std::string &filePath, int format, const std::map< int, Transform > &poses, const std::multimap< int, Link > &constraints=std::multimap< int, Link >(), const std::map< int, double > &stamps=std::map< int, double >(), const ParametersMap ¶meters=ParametersMap())
std::vector< V > uListToVector(const std::list< V > &list)
int32_t lastFrameFromSegmentLength(std::vector< float > &dist, int32_t first_frame, float len)
std::vector< V > uValues(const std::multimap< K, V > &mm)
std::pair< int, float > Pair
void RTABMAP_EXP computeMinMax(const std::map< int, Transform > &poses, cv::Vec3f &min, cv::Vec3f &max)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void RTABMAP_EXP calcRelativeErrors(const std::vector< Transform > &poses_gt, const std::vector< Transform > &poses_result, float &t_err, float &r_err)
std::map< int, Transform > RTABMAP_EXP findNearestPoses(int nodeId, const std::map< int, Transform > &poses, float radius, float angle=0.0f, int k=0)
bool RTABMAP_EXP importPoses(const std::string &filePath, int format, std::map< int, Transform > &poses, std::multimap< int, Link > *constraints=0, std::map< int, double > *stamps=0)
ULogger class and convenient macros.
std::list< std::map< int, Transform > > RTABMAP_EXP getPaths(std::map< int, Transform > poses, const std::multimap< int, Link > &links)
GLM_FUNC_DECL genType acos(genType const &x)
GLM_FUNC_DECL T yaw(detail::tquat< T, P > const &x)
void setCostSoFar(float costSoFar)
bool operator()(Pair const &a, Pair const &b) const
std::multimap< int, Link > getLinks(int signatureId, bool lookInDatabase=false, bool withLandmarks=false) const
std::multimap< int, Link > getAllLinks(bool lookInDatabase, bool ignoreNullLinks=true, bool withLandmarks=false) const
static const GLushort kIndices[]
const Transform & transform() const
bool saveGraph(const std::string &fileName, const std::map< int, Transform > &poses, const std::multimap< int, Link > &edgeConstraints)
GLM_FUNC_DECL genType::value_type length(genType const &x)
static bool loadGraph(const std::string &fileName, std::map< int, Transform > &poses, std::multimap< int, Link > &edgeConstraints)
float RTABMAP_EXP computePathLength(const std::vector< std::pair< int, Transform > > &path, unsigned int fromIndex=0, unsigned int toIndex=0)
std::string UTILITE_EXP uFormat(const char *fmt,...)
std::string UTILITE_EXP uNumber2Str(unsigned int number)
std::map< int, float > RTABMAP_EXP findNearestNodes(int nodeId, const std::map< int, Transform > &poses, float radius, float angle=0.0f, int k=0)
V uValue(const std::map< K, V > &m, const K &key, const V &defaultValue=V())
void setFromId(int fromId)
std::map< int, Transform > RTABMAP_EXP frustumPosesFiltering(const std::map< int, Transform > &poses, const Transform &cameraPose, float horizontalFOV=45.0f, float verticalFOV=45.0f, float nearClipPlaneDistance=0.1f, float farClipPlaneDistance=100.0f, bool negative=false)
void RTABMAP_EXP calcKittiSequenceErrors(const std::vector< Transform > &poses_gt, const std::vector< Transform > &poses_result, float &t_err, float &r_err)
errors(int32_t first_frame, float r_err, float t_err, float len, float speed)