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);
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 std::list<std::pair<int, Transform> > posesList;
108 for(std::map<int, Transform>::const_iterator
iter=poses.lower_bound(0);
iter!=poses.end(); ++
iter)
110 posesList.push_back(*
iter);
115 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end() &&
iter->first < 0; ++
iter)
117 posesList.push_back(*
iter);
120 for(std::list<std::pair<int, Transform> >::const_iterator
iter=posesList.begin();
iter!=posesList.end(); ++
iter)
131 pose =
t.inverse() * pose;
135 pose =
t.inverse() * pose *
t;
141 if(
iter == posesList.begin())
146 fprintf(fout,
"#timestamp x y z qx qy qz qw id\n");
150 fprintf(fout,
"#timestamp x y z qx qy qz qw\n");
155 fprintf(fout,
"%f %f %f %f %f %f %f %f%s\n",
156 stamps.at(
iter->first),
176 pose =
t.inverse() * pose *
t;
180 const float *
p = (
const float *)pose.
data();
182 fprintf(fout,
"%f",
p[0]);
183 for(
int i=1;
i<pose.
size();
i++)
185 fprintf(fout,
" %f",
p[
i]);
198 const std::string & filePath,
200 std::map<int, Transform> & poses,
201 std::multimap<int, Link> * constraints,
202 std::map<int, double> * stamps)
207 std::multimap<int, Link> constraintsTmp;
212 *constraints = constraintsTmp;
220 std::multimap<int, Link> constraintsTmp;
221 UERROR(
"Cannot import from g2o format because it is not yet supported!");
227 file.open(filePath.c_str(), std::ifstream::in);
240 if(
str.size() &&
str.at(
str.size()-1) ==
'\r')
245 if(
str.empty() ||
str.at(0) ==
'#' ||
str.at(0) ==
'%')
252 std::list<std::string> strList =
uSplit(
str,
',');
253 if(strList.size() == 17)
255 double stamp =
uStr2Double(strList.front())/1000000000.0;
262 UWARN(
"Null transform read!? line parsed: \"%s\"",
str.c_str());
268 stamps->insert(std::make_pair(
id, stamp));
275 poses.insert(std::make_pair(
id, pose));
280 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());
286 if(strList.size() == 10)
300 stamps->insert(std::make_pair(
id, stamp));
303 if(poses.size() == 0)
307 pose = originPose * pose;
308 poses.insert(std::make_pair(
id, pose));
312 UERROR(
"Error parsing \"%s\" with Karlsruhe format (should have 10 values)",
str.c_str());
318 if(strList.size() == 12)
335 std::string millisecStr = strList[1];
336 while(millisecStr.size() < 6)
338 millisecStr =
"0" + millisecStr;
340 double stamp =
uStr2Double(strList[0] +
"." + millisecStr);
356 stamps->insert(std::make_pair(
id, stamp));
362 UERROR(
"Error parsing \"%s\" with St Lucia format (should have 12 values, e.g., 101215_153851_Ins0.log)",
str.c_str());
368 if(strList.size() == 25)
382 stamps->insert(std::make_pair(
id, stamp));
388 Transform & previousPose = poses.at(
id-1);
390 previousPose =
Transform(previousPose.
x(), previousPose.
y(),
yaw);
396 UERROR(
"Error parsing \"%s\" with Malaga Urban format (should have 25 values, *_GPS.txt)",
str.c_str());
402 if(strList.size() == 3)
415 stamps->insert(std::make_pair(
id, stamp));
421 Transform & previousPose = poses.at(
id-1);
423 previousPose =
Transform(previousPose.
x(), previousPose.
y(),
yaw);
426 if(poses.size() == 0)
430 pose = originPose * pose;
431 poses.insert(std::make_pair(
id, pose));
435 UDEBUG(
"Not valid values detected: \"%s\"",
str.c_str());
440 UERROR(
"Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)",
str.c_str(), (
int)strList.size());
445 std::list<std::string> strList =
uSplit(
str);
446 if((strList.size() >= 8 &&
format!=11) || (strList.size() == 9 &&
format==11))
459 UWARN(
"Null transform read!? line parsed: \"%s\"",
str.c_str());
465 stamps->insert(std::make_pair(
id, stamp));
474 pose =
t * pose *
t.inverse();
480 poses.insert(std::make_pair(
id, pose));
485 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());
498 pose =
t * pose *
t.inverse();
500 poses.insert(std::make_pair(
id, pose));
511 const std::string & filePath,
512 const std::map<int, GPS> & gpsValues,
515 UDEBUG(
"%s", filePath.c_str());
516 std::string tmpPath = filePath;
520 if(ext.compare(
"kml")!=0 && ext.compare(
"txt")!=0)
522 UERROR(
"Only txt and kml formats are supported!");
528 fopen_s(&fout, tmpPath.c_str(),
"w");
530 fout = fopen(tmpPath.c_str(),
"w");
534 if(ext.compare(
"kml")==0)
537 for(std::map<int, GPS>::const_iterator
iter=gpsValues.begin();
iter!=gpsValues.end(); ++
iter)
546 unsigned int abgr = 0xFF << 24 | (rgba & 0xFF) << 16 | (rgba & 0xFF00) | ((rgba >> 16) &0xFF);
548 std::string colorHexa =
uFormat(
"%08x", abgr);
550 fprintf(fout,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
551 fprintf(fout,
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
552 fprintf(fout,
"<Document>\n"
553 " <name>%s</name>\n", tmpPath.c_str());
554 fprintf(fout,
" <StyleMap id=\"msn_ylw-pushpin\">\n"
556 " <key>normal</key>\n"
557 " <styleUrl>#sn_ylw-pushpin</styleUrl>\n"
560 " <key>highlight</key>\n"
561 " <styleUrl>#sh_ylw-pushpin</styleUrl>\n"
564 " <Style id=\"sh_ylw-pushpin\">\n"
566 " <scale>1.2</scale>\n"
569 " <color>%s</color>\n"
572 " <Style id=\"sn_ylw-pushpin\">\n"
574 " <color>%s</color>\n"
576 " </Style>\n", colorHexa.c_str(), colorHexa.c_str());
577 fprintf(fout,
" <Placemark>\n"
579 " <styleUrl>#msn_ylw-pushpin</styleUrl>"
593 fprintf(fout,
"# stamp longitude latitude altitude error bearing\n");
594 for(std::map<int, GPS>::const_iterator
iter=gpsValues.begin();
iter!=gpsValues.end(); ++
iter)
596 fprintf(fout,
"%f %.*f %.*f %.*f %.*f %.*f\n",
597 iter->second.stamp(),
598 8,
iter->second.longitude(),
599 8,
iter->second.latitude(),
600 8,
iter->second.altitude(),
601 8,
iter->second.error(),
602 8,
iter->second.bearing());
613 float lengths[] = {100,200,300,400,500,600,700,800};
627 std::vector<float>
dist;
629 for (
unsigned int i=1;
i<poses.size();
i++) {
632 float dx =
P1.x()-
P2.x();
633 float dy =
P1.y()-
P2.y();
634 float dz =
P1.z()-
P2.z();
641 for (
unsigned int i=first_frame;
i<
dist.size();
i++)
648 float a = pose_error(0,0);
649 float b = pose_error(1,1);
650 float c = pose_error(2,2);
651 float d = 0.5*(
a+
b+
c-1.0);
656 float dx = pose_error.
x();
657 float dy = pose_error.
y();
658 float dz = pose_error.
z();
659 return sqrt(dx*dx+dy*dy+dz*dz);
663 const std::vector<Transform> &poses_gt,
664 const std::vector<Transform> &poses_result,
668 UASSERT(poses_gt.size() == poses_result.size());
671 std::vector<errors> err;
680 for (
unsigned int first_frame=0; first_frame<poses_gt.size(); first_frame+=step_size) {
696 Transform pose_delta_gt = poses_gt[first_frame].
inverse()*poses_gt[last_frame];
697 Transform pose_delta_result = poses_result[first_frame].
inverse()*poses_result[last_frame];
703 float num_frames = (
float)(last_frame-first_frame+1);
704 float speed =
len/(0.1*num_frames);
715 for (std::vector<errors>::iterator it=err.begin(); it!=err.end(); it++)
722 float num = err.size();
731 const std::vector<Transform> &poses_gt,
732 const std::vector<Transform> &poses_result,
736 UASSERT(poses_gt.size() == poses_result.size());
739 std::vector<errors> err;
742 for (
unsigned int i=0;
i<poses_gt.size()-1; ++
i)
748 float r_err = pose_error.
getAngle();
749 float t_err = pose_error.
getNorm();
752 err.push_back(
errors(
i,r_err,t_err,0,0));
759 for (std::vector<errors>::iterator it=err.begin(); it!=err.end(); it++)
766 float num = err.size();
773 const std::map<int, Transform> & groundTruth,
774 const std::map<int, Transform> & poses,
775 float & translational_rmse,
776 float & translational_mean,
777 float & translational_median,
778 float & translational_std,
779 float & translational_min,
780 float & translational_max,
781 float & rotational_rmse,
782 float & rotational_mean,
783 float & rotational_median,
784 float & rotational_std,
785 float & rotational_min,
786 float & rotational_max,
790 translational_rmse = 0.0f;
791 translational_mean = 0.0f;
792 translational_median = 0.0f;
793 translational_std = 0.0f;
794 translational_min = 0.0f;
795 translational_max = 0.0f;
797 rotational_rmse = 0.0f;
798 rotational_mean = 0.0f;
799 rotational_median = 0.0f;
800 rotational_std = 0.0f;
801 rotational_min = 0.0f;
802 rotational_max = 0.0f;
805 pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
806 cloud1.resize(poses.size());
807 cloud2.resize(poses.size());
810 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
812 std::map<int, Transform>::const_iterator jter=groundTruth.find(
iter->first);
813 if(jter != groundTruth.end())
817 idFirst =
iter->first;
819 cloud1[oi] = pcl::PointXYZ(jter->second.x(), jter->second.y(), align2D?0:jter->second.z());
820 cloud2[oi++] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(), align2D?0:
iter->second.z());
834 t = groundTruth.at(idFirst) * poses.at(idFirst).inverse();
837 std::vector<float> translationalErrors(poses.size());
838 std::vector<float> rotationalErrors(poses.size());
839 float sumTranslationalErrors = 0.0f;
840 float sumRotationalErrors = 0.0f;
841 float sumSqrdTranslationalErrors = 0.0f;
842 float sumSqrdRotationalErrors = 0.0f;
843 float radToDegree = 180.0f /
M_PI;
845 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
847 std::map<int, Transform>::const_iterator jter = groundTruth.find(
iter->first);
848 if(jter!=groundTruth.end())
851 Eigen::Vector3f xAxis(1,0,0);
853 Eigen::Vector3f
vB = jter->second.toEigen3f().linear()*xAxis;
854 double a = pcl::getAngle3D(Eigen::Vector4f(
vA[0],
vA[1],
vA[2], 0), Eigen::Vector4f(
vB[0],
vB[1],
vB[2], 0));
855 rotationalErrors[oi] =
a*radToDegree;
856 translationalErrors[oi] = pose.
getDistance(jter->second);
858 sumTranslationalErrors+=translationalErrors[oi];
859 sumSqrdTranslationalErrors+=translationalErrors[oi]*translationalErrors[oi];
860 sumRotationalErrors+=rotationalErrors[oi];
861 sumSqrdRotationalErrors+=rotationalErrors[oi]*rotationalErrors[oi];
865 translational_min = translational_max = translationalErrors[oi];
866 rotational_min = rotational_max = rotationalErrors[oi];
870 if(translationalErrors[oi] < translational_min)
872 translational_min = translationalErrors[oi];
874 else if(translationalErrors[oi] > translational_max)
876 translational_max = translationalErrors[oi];
879 if(rotationalErrors[oi] < rotational_min)
881 rotational_min = rotationalErrors[oi];
883 else if(rotationalErrors[oi] > rotational_max)
885 rotational_max = rotationalErrors[oi];
892 translationalErrors.resize(oi);
893 rotationalErrors.resize(oi);
896 float total =
float(oi);
897 translational_rmse =
std::sqrt(sumSqrdTranslationalErrors/total);
898 translational_mean = sumTranslationalErrors/total;
899 translational_median = translationalErrors[oi/2];
902 rotational_rmse =
std::sqrt(sumSqrdRotationalErrors/total);
903 rotational_mean = sumRotationalErrors/total;
904 rotational_median = rotationalErrors[oi/2];
911 const std::map<int, Transform> & poses,
912 const std::multimap<int, Link> & links,
913 float & maxLinearErrorRatio,
914 float & maxAngularErrorRatio,
915 float & maxLinearError,
916 float & maxAngularError,
917 const Link ** maxLinearErrorLink,
918 const Link ** maxAngularErrorLink,
921 maxLinearErrorRatio = -1;
922 maxAngularErrorRatio = -1;
924 maxAngularError = -1;
926 UDEBUG(
"poses=%d links=%d", (
int)poses.size(), (
int)links.size());
927 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
930 if(
iter->second.from() !=
iter->second.to())
940 UWARN(
"Poses are null or not invertible, aborting optimized graph max error check! (Pose %d=%s Pose %d=%s)",
946 if(maxLinearErrorLink)
948 *maxLinearErrorLink = 0;
950 if(maxAngularErrorLink)
952 *maxAngularErrorLink = 0;
954 maxLinearErrorRatio = -1;
955 maxAngularErrorRatio = -1;
957 maxAngularError = -1;
963 if(
iter->second.from() < 0)
967 linkT =
iter->second.transform().inverse();
972 linkT =
iter->second.transform();
975 float linearError =
uMax3(
978 force3DoF?0:
fabs(linkT.
z() -
t.z()));
980 float stddevLinear =
sqrt(
iter->second.transVariance(
false));
981 float linearErrorRatio = linearError/stddevLinear;
982 if(linearErrorRatio > maxLinearErrorRatio)
984 maxLinearError = linearError;
985 maxLinearErrorRatio = linearErrorRatio;
986 if(maxLinearErrorLink)
988 *maxLinearErrorLink = &
iter->second;
994 1.0 /
static_cast<double>(
iter->second.infMatrix().at<
double>(5,5)) < 9999.0)
996 float opt_roll,opt_pitch,opt_yaw;
997 float link_roll,link_pitch,link_yaw;
998 t.getEulerAngles(opt_roll, opt_pitch, opt_yaw);
1000 float angularError =
uMax3(
1001 force3DoF?0:
fabs(opt_roll - link_roll),
1002 force3DoF?0:
fabs(opt_pitch - link_pitch),
1003 fabs(opt_yaw - link_yaw));
1004 angularError = angularError>
M_PI?2*
M_PI-angularError:angularError;
1006 float stddevAngular =
sqrt(
iter->second.rotVariance(
false));
1007 float angularErrorRatio = angularError/stddevAngular;
1008 if(angularErrorRatio > maxAngularErrorRatio)
1010 maxAngularError = angularError;
1011 maxAngularErrorRatio = angularErrorRatio;
1012 if(maxAngularErrorLink)
1014 *maxAngularErrorLink = &
iter->second;
1024 std::vector<double> maxOdomInf(6,0.0);
1025 maxOdomInf.resize(6,0.0);
1026 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1030 for(
int i=0;
i<6; ++
i)
1032 const double &
v =
iter->second.infMatrix().at<
double>(
i,
i);
1033 if(maxOdomInf[
i] <
v)
1040 if(maxOdomInf[0] == 0.0)
1051 std::multimap<int, Link> & links,
1057 std::multimap<int, Link>::iterator
iter = links.find(from);
1058 while(
iter != links.end() &&
iter->first == from)
1070 iter = links.find(to);
1071 while(
iter != links.end() &&
iter->first == to)
1084 std::multimap<
int, std::pair<int, Link::Type> > & links,
1090 std::multimap<int, std::pair<int, Link::Type> >
::iterator iter = links.find(from);
1091 while(
iter != links.end() &&
iter->first == from)
1103 iter = links.find(to);
1104 while(
iter != links.end() &&
iter->first == to)
1117 std::multimap<int, int> & links,
1122 std::multimap<int, int>::iterator
iter = links.find(from);
1123 while(
iter != links.end() &&
iter->first == from)
1125 if(
iter->second == to)
1135 iter = links.find(to);
1136 while(
iter != links.end() &&
iter->first == to)
1138 if(
iter->second == from)
1148 const std::multimap<int, Link> & links,
1154 std::multimap<int, Link>::const_iterator
iter = links.find(from);
1155 while(
iter != links.end() &&
iter->first == from)
1167 iter = links.find(to);
1168 while(
iter != links.end() &&
iter->first == to)
1180 std::multimap<int, std::pair<int, Link::Type> >::const_iterator
findLink(
1181 const std::multimap<
int, std::pair<int, Link::Type> > & links,
1187 std::multimap<int, std::pair<int, Link::Type> >::const_iterator
iter = links.find(from);
1188 while(
iter != links.end() &&
iter->first == from)
1200 iter = links.find(to);
1201 while(
iter != links.end() &&
iter->first == to)
1214 const std::multimap<int, int> & links,
1219 std::multimap<int, int>::const_iterator
iter = links.find(from);
1220 while(
iter != links.end() &&
iter->first == from)
1222 if(
iter->second == to)
1232 iter = links.find(to);
1233 while(
iter != links.end() &&
iter->first == to)
1235 if(
iter->second == from)
1246 const std::multimap<int, Link> & links,
1249 std::list<Link> output;
1250 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter != links.end(); ++
iter)
1252 if(
iter->second.from() == from)
1254 output.push_back(
iter->second);
1256 else if(
iter->second.to() == from)
1258 output.push_back(
iter->second.inverse());
1265 const std::multimap<int, Link> & links)
1267 std::multimap<int, Link> output;
1268 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1272 output.insert(*
iter);
1279 const std::multimap<int, Link> & links,
1283 std::multimap<int, Link> output;
1284 for(std::multimap<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1288 if((!inverted &&
iter->second.from() !=
iter->second.to())||
1289 (inverted &&
iter->second.from() ==
iter->second.to()))
1291 output.insert(*
iter);
1294 else if((!inverted &&
iter->second.type() != filteredType)||
1295 (inverted &&
iter->second.type() == filteredType))
1297 output.insert(*
iter);
1304 const std::map<int, Link> & links,
1308 std::map<int, Link> output;
1309 for(std::map<int, Link>::const_iterator
iter=links.begin();
iter!=links.end(); ++
iter)
1313 if((!inverted &&
iter->second.from() !=
iter->second.to())||
1314 (inverted &&
iter->second.from() ==
iter->second.to()))
1316 output.insert(*
iter);
1319 else if((!inverted &&
iter->second.type() != filteredType)||
1320 (inverted &&
iter->second.type() == filteredType))
1322 output.insert(*
iter);
1329 const std::map<int, Transform> & poses,
1331 float horizontalFOV,
1333 float nearClipPlaneDistance,
1334 float farClipPlaneDistance,
1337 std::map<int, Transform> output;
1341 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1342 std::vector<int> ids(poses.size());
1344 cloud->resize(poses.size());
1345 ids.resize(poses.size());
1347 for(std::map<int, rtabmap::Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)
1349 if(!
iter->second.isNull())
1351 (*cloud)[oi] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
1352 ids[oi++] =
iter->first;
1360 pcl::IndicesPtr(
new std::vector<int>),
1364 nearClipPlaneDistance,
1365 farClipPlaneDistance,
1369 for(
unsigned int i=0;
i<
indices->size(); ++
i)
1371 output.insert(*poses.find(ids[
indices->at(
i)]));
1378 const std::map<int, Transform> & poses,
1383 if(poses.size() > 2 && radius > 0.0f)
1385 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1386 cloud->resize(poses.size());
1388 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter, ++
i)
1390 (*cloud)[
i] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
1391 UASSERT_MSG(pcl::isFinite((*cloud)[
i]),
uFormat(
"Invalid pose (%d) %s",
iter->first,
iter->second.prettyPrint().c_str()).c_str());
1396 std::vector<Transform> transforms =
uValues(poses);
1398 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1399 tree->setInputCloud(cloud);
1400 std::set<int> indicesChecked;
1401 std::set<int> indicesKept;
1403 for(
unsigned int i=0;
i<cloud->size(); ++
i)
1405 if(indicesChecked.find(
i) == indicesChecked.end())
1408 std::vector<float> kDistances;
1409 tree->radiusSearch(cloud->at(
i), radius,
kIndices, kDistances);
1411 std::set<int> cloudIndices;
1412 const Transform & currentT = transforms.at(
i);
1416 if(indicesChecked.find(
kIndices[
j]) == indicesChecked.end())
1423 double a = pcl::getAngle3D(Eigen::Vector4f(
vA[0],
vA[1],
vA[2], 0), Eigen::Vector4f(
vB[0],
vB[1],
vB[2], 0));
1438 bool lastAdded =
false;
1439 for(std::set<int>::reverse_iterator
iter = cloudIndices.rbegin();
iter!=cloudIndices.rend(); ++
iter)
1443 indicesKept.insert(*
iter);
1446 indicesChecked.insert(*
iter);
1451 bool firstAdded =
false;
1452 for(std::set<int>::iterator
iter = cloudIndices.begin();
iter!=cloudIndices.end(); ++
iter)
1456 indicesKept.insert(*
iter);
1459 indicesChecked.insert(*
iter);
1467 UINFO(
"Cloud filtered In = %d, Out = %d (radius=%f angle=%f keepLatest=%d)", cloud->size(), indicesKept.size(), radius,
angle, keepLatest?1:0);
1471 std::map<int, Transform> keptPoses;
1472 for(std::set<int>::iterator
iter = indicesKept.begin();
iter!=indicesKept.end(); ++
iter)
1474 keptPoses.insert(std::make_pair(
names.at(*
iter), transforms.at(*
iter)));
1478 keptPoses.insert(*poses.begin());
1479 keptPoses.insert(*poses.rbegin());
1491 std::multimap<int, int> clusters;
1492 if(poses.size() > 1 && radius > 0.0f)
1494 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1495 cloud->resize(poses.size());
1497 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter, ++
i)
1499 (*cloud)[
i] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
1500 UASSERT_MSG(pcl::isFinite((*cloud)[
i]),
uFormat(
"Invalid pose (%d) %s",
iter->first,
iter->second.prettyPrint().c_str()).c_str());
1504 std::vector<int> ids =
uKeys(poses);
1505 std::vector<Transform> transforms =
uValues(poses);
1507 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1508 tree->setInputCloud(cloud);
1510 for(
unsigned int i=0;
i<cloud->size(); ++
i)
1513 std::vector<float> kDistances;
1514 tree->radiusSearch(cloud->at(
i), radius,
kIndices, kDistances);
1516 std::set<int> cloudIndices;
1517 const Transform & currentT = transforms.at(
i);
1528 double a = pcl::getAngle3D(Eigen::Vector4f(
vA[0],
vA[1],
vA[2], 0), Eigen::Vector4f(
vB[0],
vB[1],
vB[2], 0));
1531 clusters.insert(std::make_pair(ids[
i], ids[
kIndices[
j]]));
1536 clusters.insert(std::make_pair(ids[
i], ids[
kIndices[
j]]));
1546 const std::map<int, Transform> & poses,
1547 const std::multimap<int, Link> & links,
1548 std::multimap<int, int> & hyperNodes,
1549 std::multimap<int, Link> & hyperLinks)
1551 UINFO(
"Input: poses=%d links=%d", (
int)poses.size(), (
int)links.size());
1553 std::map<int, int> posesToHyperNodes;
1554 std::map<int, std::multimap<int, Link> > clusterloopClosureLinks;
1557 std::multimap<int, Link> bidirectionalLoopClosureLinks;
1558 for(std::multimap<int, Link>::const_iterator jter=links.begin(); jter!=links.end(); ++jter)
1562 jter->second.userDataCompressed().empty())
1564 if(
uContains(poses, jter->second.from()) &&
1567 UASSERT_MSG(
graph::findLink(links, jter->second.to(), jter->second.from(),
false) == links.end(),
"Input links should be unique!");
1568 bidirectionalLoopClosureLinks.insert(std::make_pair(jter->second.from(), jter->second));
1574 UINFO(
"Clustering hyper nodes...");
1576 for(std::map<int, Transform>::const_reverse_iterator
iter=poses.rbegin();
iter!=poses.rend(); ++
iter)
1578 if(posesToHyperNodes.find(
iter->first) == posesToHyperNodes.end())
1580 int hyperNodeId =
iter->first;
1581 std::list<int> loopClosures;
1582 std::set<int> loopClosuresAdded;
1583 loopClosures.push_back(
iter->first);
1584 std::multimap<int, Link> clusterLinks;
1585 while(loopClosures.size())
1587 int id = loopClosures.front();
1588 loopClosures.pop_front();
1590 UASSERT(posesToHyperNodes.find(
id) == posesToHyperNodes.end());
1592 posesToHyperNodes.insert(std::make_pair(
id, hyperNodeId));
1593 hyperNodes.insert(std::make_pair(hyperNodeId,
id));
1595 for(std::multimap<int, Link>::const_iterator jter=bidirectionalLoopClosureLinks.find(
id); jter!=bidirectionalLoopClosureLinks.end() && jter->first==
id; ++jter)
1597 if(posesToHyperNodes.find(jter->second.to()) == posesToHyperNodes.end() &&
1598 loopClosuresAdded.find(jter->second.to()) == loopClosuresAdded.end())
1600 loopClosures.push_back(jter->second.to());
1601 loopClosuresAdded.insert(jter->second.to());
1602 clusterLinks.insert(*jter);
1603 clusterLinks.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
1604 if(jter->second.from() < jter->second.to())
1606 UWARN(
"Child to Parent link? %d->%d (type=%d)",
1607 jter->second.from(),
1609 jter->second.type());
1614 UASSERT(clusterloopClosureLinks.find(hyperNodeId) == clusterloopClosureLinks.end());
1615 clusterloopClosureLinks.insert(std::make_pair(hyperNodeId, clusterLinks));
1616 UDEBUG(
"Created hyper node %d with %d children (%f%%)",
1617 hyperNodeId, (
int)loopClosuresAdded.size(),
float(posesToHyperNodes.size())/
float(poses.size())*100.0f);
1620 UINFO(
"Clustering hyper nodes... done! (%f s)",
timer.ticks());
1623 UINFO(
"Creating hyper links...");
1625 for(std::multimap<int, Link>::const_reverse_iterator jter=links.rbegin(); jter!=links.rend(); ++jter)
1629 !jter->second.userDataCompressed().empty()) &&
1630 uContains(poses, jter->second.from()) &&
1633 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.from()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1634 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.to()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1635 int hyperNodeIDFrom = posesToHyperNodes.at(jter->second.from());
1636 int hyperNodeIDTo = posesToHyperNodes.at(jter->second.to());
1639 if(hyperNodeIDFrom != hyperNodeIDTo)
1641 std::multimap<int, Link>::iterator tmpIter =
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo);
1642 if(tmpIter!=hyperLinks.end() &&
1643 hyperNodeIDFrom == jter->second.from() &&
1644 hyperNodeIDTo == jter->second.to() &&
1649 hyperLinks.erase(tmpIter);
1653 if(
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo) == hyperLinks.end())
1655 UASSERT(clusterloopClosureLinks.find(hyperNodeIDFrom) != clusterloopClosureLinks.end());
1656 UASSERT(clusterloopClosureLinks.find(hyperNodeIDTo) != clusterloopClosureLinks.end());
1657 std::multimap<int, Link> tmpLinks = clusterloopClosureLinks.at(hyperNodeIDFrom);
1658 tmpLinks.insert(clusterloopClosureLinks.at(hyperNodeIDTo).begin(), clusterloopClosureLinks.at(hyperNodeIDTo).end());
1659 tmpLinks.insert(std::make_pair(jter->second.from(), jter->second));
1661 std::list<int>
path =
computePath(tmpLinks, hyperNodeIDFrom, hyperNodeIDTo,
false,
true);
1663 uFormat(
"path.size()=%d, hyperNodeIDFrom=%d, hyperNodeIDTo=%d",
1666 hyperNodeIDTo).c_str());
1668 if(
path.size() > 10)
1670 UWARN(
"Large path! %d nodes", (
int)
path.size());
1671 std::stringstream
stream;
1685 std::list<int>::iterator
iter=
path.begin();
1689 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1690 UASSERT(foundIter != tmpLinks.end());
1691 Link hyperLink = foundIter->second;
1697 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1698 UASSERT(foundIter != tmpLinks.end());
1699 hyperLink = hyperLink.
merge(foundIter->second, jter->second.type());
1705 UASSERT(hyperLink.
to() == hyperNodeIDTo);
1706 hyperLinks.insert(std::make_pair(hyperNodeIDFrom, hyperLink));
1708 UDEBUG(
"Created hyper link %d->%d (%f%%)",
1709 hyperLink.
from(), hyperLink.
to(),
float(
i)/
float(links.size())*100.0f);
1712 UWARN(
"Large hyper link %d->%d (%f m)! original %d->%d (%f m)",
1716 jter->second.from(),
1718 jter->second.transform().getNorm());
1726 UINFO(
"Creating hyper links... done! (%f s)",
timer.ticks());
1772 typedef std::pair<int, float>
Pair;
1777 return a.second >
b.second;
1783 const std::map<int, rtabmap::Transform> & poses,
1784 const std::multimap<int, int> & links,
1787 bool updateNewCosts)
1789 std::list<std::pair<int, Transform> >
path;
1791 int startNode = from;
1794 std::map<int, Node>
nodes;
1795 nodes.insert(std::make_pair(startNode,
Node(startNode, 0, poses.at(startNode))));
1796 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1797 std::multimap<float, int> pqmap;
1800 pqmap.insert(std::make_pair(0, startNode));
1804 pq.push(
Pair(startNode, 0));
1807 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1812 currentNode = &
nodes.find(pqmap.begin()->second)->second;
1813 pqmap.erase(pqmap.begin());
1817 currentNode = &
nodes.find(pq.top().first)->second;
1823 if(currentNode->
id() == endNode)
1825 while(currentNode->
id()!=startNode)
1827 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
1828 currentNode = &
nodes.find(currentNode->
fromId())->second;
1830 path.push_front(std::make_pair(startNode, poses.at(startNode)));
1835 for(std::multimap<int, int>::const_iterator
iter = links.find(currentNode->
id());
1836 iter!=links.end() &&
iter->first == currentNode->
id();
1839 std::map<int, Node>::iterator nodeIter =
nodes.find(
iter->second);
1840 if(nodeIter ==
nodes.end())
1842 std::map<int, rtabmap::Transform>::const_iterator poseIter = poses.find(
iter->second);
1843 if(poseIter == poses.end())
1845 UERROR(
"Next pose %d (from %d) should be found in poses! Ignoring it!",
iter->second,
iter->first);
1849 Node n(
iter->second, currentNode->
id(), poseIter->second);
1851 n.setDistToEnd(
n.distFrom(endPose));
1853 nodes.insert(std::make_pair(
iter->second,
n));
1856 pqmap.insert(std::make_pair(
n.totalCost(),
n.id()));
1860 pq.push(
Pair(
n.id(),
n.totalCost()));
1864 else if(updateNewCosts && nodeIter->second.isOpened())
1866 float newCostSoFar = currentNode->
costSoFar() + currentNode->
distFrom(nodeIter->second.pose());
1867 if(nodeIter->second.costSoFar() > newCostSoFar)
1870 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1872 if(mapIter->second == nodeIter->first)
1874 pqmap.erase(mapIter);
1875 nodeIter->second.setCostSoFar(newCostSoFar);
1876 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1889 const std::multimap<int, Link> & links,
1892 bool updateNewCosts,
1893 bool useSameCostForAllLinks)
1895 std::list<int>
path;
1897 int startNode = from;
1899 std::map<int, Node>
nodes;
1901 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1902 std::multimap<float, int> pqmap;
1905 pqmap.insert(std::make_pair(0, startNode));
1909 pq.push(
Pair(startNode, 0));
1912 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1917 currentNode = &
nodes.find(pqmap.begin()->second)->second;
1918 pqmap.erase(pqmap.begin());
1922 currentNode = &
nodes.find(pq.top().first)->second;
1928 if(currentNode->
id() == endNode)
1930 while(currentNode->
id()!=startNode)
1932 path.push_front(currentNode->
id());
1933 currentNode = &
nodes.find(currentNode->
fromId())->second;
1935 path.push_front(startNode);
1940 for(std::multimap<int, Link>::const_iterator
iter = links.find(currentNode->
id());
1941 iter!=links.end() &&
iter->first == currentNode->
id();
1944 std::map<int, Node>::iterator nodeIter =
nodes.find(
iter->second.to());
1946 if(!useSameCostForAllLinks)
1948 cost =
iter->second.transform().getNorm();
1950 if(nodeIter ==
nodes.end())
1954 n.setCostSoFar(currentNode->
costSoFar() + cost);
1955 nodes.insert(std::make_pair(
iter->second.to(),
n));
1958 pqmap.insert(std::make_pair(
n.totalCost(),
n.id()));
1962 pq.push(
Pair(
n.id(),
n.totalCost()));
1965 else if(!useSameCostForAllLinks && updateNewCosts && nodeIter->second.isOpened())
1967 float newCostSoFar = currentNode->
costSoFar() + cost;
1968 if(nodeIter->second.costSoFar() > newCostSoFar)
1971 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1973 if(mapIter->second == nodeIter->first)
1975 pqmap.erase(mapIter);
1976 nodeIter->second.setCostSoFar(newCostSoFar);
1977 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1994 bool lookInDatabase,
1995 bool updateNewCosts,
1996 float linearVelocity,
1997 float angularVelocity)
2002 std::list<std::pair<int, Transform> >
path;
2003 UDEBUG(
"fromId=%d, toId=%d, lookInDatabase=%d, updateNewCosts=%d, linearVelocity=%f, angularVelocity=%f",
2011 std::multimap<int, Link> allLinks;
2016 allLinks = memory->
getAllLinks(lookInDatabase,
true,
true);
2017 for(std::multimap<int, Link>::iterator
iter=allLinks.begin();
iter!=allLinks.end(); ++
iter)
2019 if(
iter->second.to() < 0)
2021 allLinks.insert(std::make_pair(
iter->second.to(),
iter->second.inverse()));
2024 UINFO(
"getting all %d links time = %f s", (
int)allLinks.size(),
t.ticks());
2028 int startNode = fromId;
2030 std::map<int, Node>
nodes;
2032 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
2033 std::multimap<float, int> pqmap;
2036 pqmap.insert(std::make_pair(0, startNode));
2040 pq.push(
Pair(startNode, 0));
2043 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
2048 currentNode = &
nodes.find(pqmap.begin()->second)->second;
2049 pqmap.erase(pqmap.begin());
2053 currentNode = &
nodes.find(pq.top().first)->second;
2059 if(currentNode->
id() == endNode)
2061 while(currentNode->
id()!=startNode)
2063 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
2064 currentNode = &
nodes.find(currentNode->
fromId())->second;
2066 path.push_front(std::make_pair(startNode, currentNode->
pose()));
2071 std::multimap<int, Link> links;
2072 if(allLinks.size() == 0)
2074 links = memory->
getLinks(currentNode->
id(), lookInDatabase,
true);
2078 for(std::multimap<int, Link>::const_iterator
iter = allLinks.lower_bound(currentNode->
id());
2079 iter!=allLinks.end() &&
iter->first == currentNode->
id();
2082 links.insert(std::make_pair(
iter->second.to(),
iter->second));
2085 for(std::multimap<int, Link>::const_iterator
iter = links.begin();
iter!=links.end(); ++
iter)
2087 if(
iter->second.from() !=
iter->second.to())
2091 if(linearVelocity <= 0.0
f && angularVelocity <= 0.0
f)
2094 cost =
iter->second.transform().getNorm();
2098 if(linearVelocity > 0.0
f)
2100 cost +=
iter->second.transform().getNorm()/linearVelocity;
2102 if(angularVelocity > 0.0
f)
2104 Eigen::Vector4f
v1 = Eigen::Vector4f(nextPose.
x()-currentNode->
pose().
x(), nextPose.
y()-currentNode->
pose().
y(), nextPose.
z()-currentNode->
pose().
z(), 1.0f);
2107 cost +=
angle / angularVelocity;
2111 std::map<int, Node>::iterator nodeIter =
nodes.find(
iter->first);
2112 if(nodeIter ==
nodes.end())
2114 Node n(
iter->second.to(), currentNode->
id(), nextPose);
2116 n.setCostSoFar(currentNode->
costSoFar() + cost);
2117 nodes.insert(std::make_pair(
iter->second.to(),
n));
2120 pqmap.insert(std::make_pair(
n.totalCost(),
n.id()));
2124 pq.push(
Pair(
n.id(),
n.totalCost()));
2127 else if(updateNewCosts && nodeIter->second.isOpened())
2129 float newCostSoFar = currentNode->
costSoFar() + cost;
2130 if(nodeIter->second.costSoFar() > newCostSoFar)
2133 nodeIter->second.setPose(nextPose);
2136 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
2138 if(mapIter->second == nodeIter->first)
2140 pqmap.erase(mapIter);
2141 nodeIter->second.setCostSoFar(newCostSoFar);
2142 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
2155 std::stringstream
stream;
2157 std::list<std::pair<int, Transform> >::const_iterator previousIter =
path.end();
2159 for(std::list<std::pair<int, Transform> >::const_iterator
iter=
path.begin();
iter!=
path.end();++
iter)
2166 if(previousIter!=
path.end())
2171 std::multimap<int, Link>::iterator jter =
graph::findLink(allLinks, previousIter->first,
iter->first);
2172 if(jter != allLinks.end())
2182 ++linkTypes[jter->second.type()];
2183 stream <<
"[" << jter->second.type() <<
"]";
2184 length += jter->second.transform().getNorm();
2194 std::stringstream streamB;
2195 for(
unsigned int i=0;
i<linkTypes.size(); ++
i)
2201 streamB <<
i <<
"=" << linkTypes[
i];
2203 UDEBUG(
"Link types = %s", streamB.str().c_str());
2210 const std::map<int, rtabmap::Transform> & poses,
2215 std::map<int, float> nearestNodes =
findNearestNodes(targetPose, poses, 0, 0, 1);
2216 if(!nearestNodes.empty())
2218 id = nearestNodes.begin()->first;
2221 *
distance = nearestNodes.begin()->second;
2230 const std::map<int, Transform> & poses,
2237 std::map<int, Transform> nodesMinusTarget = poses;
2238 Transform targetPose = poses.at(nodeId);
2239 nodesMinusTarget.erase(nodeId);
2246 const std::map<int, Transform> & poses,
2254 std::map<int, float> foundNodes;
2260 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
2261 cloud->resize(poses.size());
2262 std::vector<int> ids(poses.size());
2264 for(std::map<int, Transform>::const_iterator
iter = poses.begin();
iter!=poses.end(); ++
iter)
2266 (*cloud)[oi] = pcl::PointXYZ(
iter->second.x(),
iter->second.y(),
iter->second.z());
2267 UASSERT_MSG(pcl::isFinite((*cloud)[oi]),
uFormat(
"Invalid pose (%d) %s",
iter->first,
iter->second.prettyPrint().c_str()).c_str());
2268 ids[oi] =
iter->first;
2276 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
2277 kdTree->setInputCloud(cloud);
2278 std::vector<int>
ind;
2279 std::vector<float> sqrdDist;
2280 pcl::PointXYZ pt(targetPose.
x(), targetPose.
y(), targetPose.
z());
2283 kdTree->radiusSearch(pt, radius,
ind, sqrdDist, k);
2287 kdTree->nearestKSearch(pt, k,
ind, sqrdDist);
2290 for(
unsigned int i=0;
i<
ind.size(); ++
i)
2299 double a = pcl::getAngle3D(Eigen::Vector4f(
vA[0],
vA[1],
vA[2], 0), Eigen::Vector4f(
vB[0],
vB[1],
vB[2], 0));
2302 foundNodes.insert(std::make_pair(ids[
ind[
i]], sqrdDist[
i]));
2307 foundNodes.insert(std::make_pair(ids[
ind[
i]], sqrdDist[
i]));
2312 UDEBUG(
"found nodes=%d", (
int)foundNodes.size());
2319 const std::map<int, Transform> & poses,
2326 std::map<int, Transform> nodesMinusTarget = poses;
2327 Transform targetPose = poses.at(nodeId);
2328 nodesMinusTarget.erase(nodeId);
2334 const std::map<int, Transform> & poses,
2340 std::map<int, Transform> foundPoses;
2341 for(std::map<int, float>::iterator
iter=nearestNodes.begin();
iter!=nearestNodes.end(); ++
iter)
2343 foundPoses.insert(*poses.find(
iter->first));
2345 UDEBUG(
"found nodes=%d/%d (radius=%f, angle=%f, k=%d)", (
int)foundPoses.size(), (
int)poses.size(), radius,
angle, k);
2354 std::map<int, float>
getNodesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius)
2362 std::map<int, Transform>
getPosesInRadius(
int nodeId,
const std::map<int, Transform> & nodes,
float radius,
float angle)
2373 const std::vector<std::pair<int, Transform> > & path,
2374 unsigned int fromIndex,
2375 unsigned int toIndex)
2380 UASSERT(fromIndex <
path.size() && toIndex <
path.size() && fromIndex <= toIndex);
2381 if(fromIndex >= toIndex)
2383 toIndex = (
unsigned int)
path.size()-1;
2385 float x=0,
y=0,
z=0;
2386 for(
unsigned int i=fromIndex;
i<toIndex-1; ++
i)
2398 const std::map<int, Transform> & path)
2403 float x=0,
y=0,
z=0;
2404 std::map<int, Transform>::const_iterator
iter=
path.begin();
2410 x +=
fabs(previousPose.
x() - currentPose.
x());
2411 y +=
fabs(previousPose.
y() - currentPose.
y());
2412 z +=
fabs(previousPose.
z() - currentPose.
z());
2413 previousPose = currentPose;
2422 std::map<int, Transform> poses,
2423 const std::multimap<int, Link> & links)
2425 std::list<std::map<int, Transform> > paths;
2426 if(poses.size() && links.size())
2431 std::map<int, Transform>
path;
2432 for(std::map<int, Transform>::iterator
iter=poses.begin();
iter!=poses.end();)
2434 std::multimap<int, Link>::const_iterator jter =
findLink(links,
path.rbegin()->first,
iter->first);
2438 poses.erase(
iter++);
2446 paths.push_back(
path);
2459 min[0] =
max[0] = poses.begin()->second.x();
2460 min[1] =
max[1] = poses.begin()->second.y();
2461 min[2] =
max[2] = poses.begin()->second.z();
2462 for(std::map<int, Transform>::const_iterator
iter=poses.begin();
iter!=poses.end(); ++
iter)