39 #include <pcl/search/kdtree.h> 40 #include <pcl/common/eigen.h> 41 #include <pcl/common/common.h> 54 const std::string & filePath,
56 const std::map<int, Transform> & poses,
57 const std::multimap<int, Link> & constraints,
58 const std::map<int, double> & stamps,
61 UDEBUG(
"%s", filePath.c_str());
62 std::string tmpPath = filePath;
88 if(stamps.size() != poses.size())
90 UERROR(
"When exporting poses to format 1 (RGBD-SLAM), stamps and poses maps should have the same size!");
97 fopen_s(&fout, tmpPath.c_str(),
"w");
99 fout = fopen(tmpPath.c_str(),
"w");
103 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
121 fprintf(fout,
"%f %f %f %f %f %f %f %f\n",
122 stamps.at(iter->first),
145 const float * p = (
const float *)pose.
data();
147 fprintf(fout,
"%f", p[0]);
148 for(
int i=1; i<pose.
size(); i++)
150 fprintf(fout,
" %f", p[i]);
163 const std::string & filePath,
165 std::map<int, Transform> & poses,
166 std::multimap<int, Link> * constraints,
167 std::map<int, double> * stamps)
169 UDEBUG(
"%s format=%d", filePath.c_str(), format);
172 std::multimap<int, Link> constraintsTmp;
177 *constraints = constraintsTmp;
185 std::multimap<int, Link> constraintsTmp;
186 UERROR(
"Cannot import from g2o format because it is not yet supported!");
192 file.open(filePath.c_str(), std::ifstream::in);
203 std::getline(file, str);
205 if(str.size() && str.at(str.size()-1) ==
'\r')
207 str = str.substr(0, str.size()-1);
210 if(str.empty() || str.at(0) ==
'#' || str.at(0) ==
'%')
217 std::list<std::string> strList =
uSplit(str,
',');
218 if(strList.size() == 17)
220 double stamp =
uStr2Double(strList.front())/1000000000.0;
227 UWARN(
"Null transform read!? line parsed: \"%s\"", str.c_str());
233 stamps->insert(std::make_pair(
id, stamp));
240 poses.insert(std::make_pair(
id, pose));
245 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());
251 if(strList.size() == 10)
256 double stamp =
uStr2Double(strList[0].insert(10, 1,
'.'));
265 stamps->insert(std::make_pair(
id, stamp));
268 if(poses.size() == 0)
272 pose = originPose * pose;
273 poses.insert(std::make_pair(
id, pose));
277 UERROR(
"Error parsing \"%s\" with Karlsruhe format (should have 10 values)", str.c_str());
283 if(strList.size() == 12)
300 std::string millisecStr = strList[1];
301 while(millisecStr.size() < 6)
303 millisecStr =
"0" + millisecStr;
305 double stamp =
uStr2Double(strList[0] +
"." + millisecStr);
321 stamps->insert(std::make_pair(
id, stamp));
323 poses.insert(std::make_pair(
id,
Transform(coordENU.x,coordENU.y,coordENU.z, roll,pitch,yaw)));
327 UERROR(
"Error parsing \"%s\" with St Lucia format (should have 12 values, e.g., 101215_153851_Ins0.log)", str.c_str());
333 if(strList.size() == 25)
347 stamps->insert(std::make_pair(
id, stamp));
353 Transform & previousPose = poses.at(
id-1);
354 yaw =
atan2(y-previousPose.
y(),x-previousPose.
x());
355 previousPose =
Transform(previousPose.x(), previousPose.y(),
yaw);
357 poses.insert(std::make_pair(
id,
Transform(x,y,z,0,0,yaw)));
361 UERROR(
"Error parsing \"%s\" with Malaga Urban format (should have 25 values, *_GPS.txt)", str.c_str());
367 if(strList.size() == 3)
380 stamps->insert(std::make_pair(
id, stamp));
386 Transform & previousPose = poses.at(
id-1);
387 yaw =
atan2(y-previousPose.
y(),x-previousPose.
x());
388 previousPose =
Transform(previousPose.x(), previousPose.y(),
yaw);
391 if(poses.size() == 0)
395 pose = originPose * pose;
396 poses.insert(std::make_pair(
id, pose));
400 UDEBUG(
"Not valid values detected: \"%s\"", str.c_str());
405 UERROR(
"Error parsing \"%s\" with NewCollege format (should have 3 values: stamp x y, found %d)", str.c_str(), (int)strList.size());
410 std::list<std::string> strList =
uSplit(str);
411 if(strList.size() == 8)
415 str =
uJoin(strList,
" ");
419 UWARN(
"Null transform read!? line parsed: \"%s\"", str.c_str());
425 stamps->insert(std::make_pair(
id, stamp));
437 poses.insert(std::make_pair(
id, pose));
442 UERROR(
"Error parsing \"%s\" with RGBD-SLAM format (should have 8 values: stamp x y z qw qx qy qz)", str.c_str());
457 poses.insert(std::make_pair(
id, pose));
468 const std::string & filePath,
469 const std::map<int, GPS> & gpsValues,
472 UDEBUG(
"%s", filePath.c_str());
473 std::string tmpPath = filePath;
477 if(ext.compare(
"kml")!=0 && ext.compare(
"txt")!=0)
479 UERROR(
"Only txt and kml formats are supported!");
485 fopen_s(&fout, tmpPath.c_str(),
"w");
487 fout = fopen(tmpPath.c_str(),
"w");
491 if(ext.compare(
"kml")==0)
494 for(std::map<int, GPS>::const_iterator iter=gpsValues.begin(); iter!=gpsValues.end(); ++iter)
496 values +=
uFormat(
"%f,%f,%f ", iter->second.longitude(), iter->second.latitude(), iter->second.altitude());
500 unsigned int abgr = 0xFF << 24 | (rgba & 0xFF) << 16 | (rgba & 0xFF00) | ((rgba >> 16) &0xFF);
502 std::string colorHexa =
uFormat(
"%08x", abgr);
504 fprintf(fout,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
505 fprintf(fout,
"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n");
506 fprintf(fout,
"<Document>\n" 507 " <name>%s</name>\n", tmpPath.c_str());
508 fprintf(fout,
" <StyleMap id=\"msn_ylw-pushpin\">\n" 510 " <key>normal</key>\n" 511 " <styleUrl>#sn_ylw-pushpin</styleUrl>\n" 514 " <key>highlight</key>\n" 515 " <styleUrl>#sh_ylw-pushpin</styleUrl>\n" 518 " <Style id=\"sh_ylw-pushpin\">\n" 520 " <scale>1.2</scale>\n" 523 " <color>%s</color>\n" 526 " <Style id=\"sn_ylw-pushpin\">\n" 528 " <color>%s</color>\n" 530 " </Style>\n", colorHexa.c_str(), colorHexa.c_str());
531 fprintf(fout,
" <Placemark>\n" 533 " <styleUrl>#msn_ylw-pushpin</styleUrl>" 542 uSplit(tmpPath,
'.').front().c_str(),
547 fprintf(fout,
"# stamp longitude latitude altitude error bearing\n");
548 for(std::map<int, GPS>::const_iterator iter=gpsValues.begin(); iter!=gpsValues.end(); ++iter)
550 fprintf(fout,
"%f %f %f %f %f %f\n",
551 iter->second.stamp(),
552 iter->second.longitude(),
553 iter->second.latitude(),
554 iter->second.altitude(),
555 iter->second.error(),
556 iter->second.bearing());
567 float lengths[] = {100,200,300,400,500,600,700,800};
576 errors (
int32_t first_frame,
float r_err,
float t_err,
float len,
float speed) :
577 first_frame(first_frame),r_err(r_err),t_err(t_err),len(len),speed(speed) {}
581 std::vector<float> dist;
583 for (
unsigned int i=1; i<poses.size(); i++) {
586 float dx = P1.
x()-P2.
x();
587 float dy = P1.
y()-P2.
y();
588 float dz = P1.
z()-P2.
z();
589 dist.push_back(dist[i-1]+
sqrt(dx*dx+dy*dy+dz*dz));
595 for (
unsigned int i=first_frame; i<dist.size(); i++)
596 if (dist[i]>dist[first_frame]+len)
602 float a = pose_error(0,0);
603 float b = pose_error(1,1);
604 float c = pose_error(2,2);
605 float d = 0.5*(a+b+c-1.0);
610 float dx = pose_error.
x();
611 float dy = pose_error.
y();
612 float dz = pose_error.
z();
613 return sqrt(dx*dx+dy*dy+dz*dz);
617 const std::vector<Transform> &poses_gt,
618 const std::vector<Transform> &poses_result,
622 UASSERT(poses_gt.size() == poses_result.size());
625 std::vector<errors> err;
640 float len = lengths[i];
657 float num_frames = (float)(last_frame-
first_frame+1);
658 float speed = len/(0.1*num_frames);
669 for (std::vector<errors>::iterator it=err.begin(); it!=err.end(); it++)
676 float num = err.size();
685 const std::map<int, Transform> & groundTruth,
686 const std::map<int, Transform> & poses,
687 float & translational_rmse,
688 float & translational_mean,
689 float & translational_median,
690 float & translational_std,
691 float & translational_min,
692 float & translational_max,
693 float & rotational_rmse,
694 float & rotational_mean,
695 float & rotational_median,
696 float & rotational_std,
697 float & rotational_min,
698 float & rotational_max)
701 translational_rmse = 0.0f;
702 translational_mean = 0.0f;
703 translational_median = 0.0f;
704 translational_std = 0.0f;
705 translational_min = 0.0f;
706 translational_max = 0.0f;
708 rotational_rmse = 0.0f;
709 rotational_mean = 0.0f;
710 rotational_median = 0.0f;
711 rotational_std = 0.0f;
712 rotational_min = 0.0f;
713 rotational_max = 0.0f;
716 pcl::PointCloud<pcl::PointXYZ> cloud1, cloud2;
717 cloud1.resize(poses.size());
718 cloud2.resize(poses.size());
721 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
723 std::map<int, Transform>::const_iterator jter=groundTruth.find(iter->first);
724 if(jter != groundTruth.end())
728 idFirst = iter->first;
730 cloud1[oi] = pcl::PointXYZ(jter->second.x(), jter->second.y(), jter->second.z());
731 cloud2[oi++] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
745 t = groundTruth.at(idFirst) * poses.at(idFirst).inverse();
748 std::vector<float> translationalErrors(poses.size());
749 std::vector<float> rotationalErrors(poses.size());
750 float sumTranslationalErrors = 0.0f;
751 float sumRotationalErrors = 0.0f;
752 float sumSqrdTranslationalErrors = 0.0f;
753 float sumSqrdRotationalErrors = 0.0f;
754 float radToDegree = 180.0f /
M_PI;
756 for(std::map<int, Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
758 std::map<int, Transform>::const_iterator jter = groundTruth.find(iter->first);
759 if(jter!=groundTruth.end())
762 Eigen::Vector3f xAxis(1,0,0);
763 Eigen::Vector3f vA = pose.
toEigen3f().linear()*xAxis;
764 Eigen::Vector3f vB = jter->second.toEigen3f().linear()*xAxis;
765 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
766 rotationalErrors[oi] = a*radToDegree;
767 translationalErrors[oi] = pose.
getDistance(jter->second);
769 sumTranslationalErrors+=translationalErrors[oi];
770 sumSqrdTranslationalErrors+=translationalErrors[oi]*translationalErrors[oi];
771 sumRotationalErrors+=rotationalErrors[oi];
772 sumSqrdRotationalErrors+=rotationalErrors[oi]*rotationalErrors[oi];
776 translational_min = translational_max = translationalErrors[oi];
777 rotational_min = rotational_max = rotationalErrors[oi];
781 if(translationalErrors[oi] < translational_min)
783 translational_min = translationalErrors[oi];
785 else if(translationalErrors[oi] > translational_max)
787 translational_max = translationalErrors[oi];
790 if(rotationalErrors[oi] < rotational_min)
792 rotational_min = rotationalErrors[oi];
794 else if(rotationalErrors[oi] > rotational_max)
796 rotational_max = rotationalErrors[oi];
803 translationalErrors.resize(oi);
804 rotationalErrors.resize(oi);
807 float total = float(oi);
808 translational_rmse =
std::sqrt(sumSqrdTranslationalErrors/total);
809 translational_mean = sumTranslationalErrors/total;
810 translational_median = translationalErrors[oi/2];
813 rotational_rmse =
std::sqrt(sumSqrdRotationalErrors/total);
814 rotational_mean = sumRotationalErrors/total;
815 rotational_median = rotationalErrors[oi/2];
826 std::multimap<int, Link> & links,
831 std::multimap<int, Link>::iterator iter = links.find(from);
832 while(iter != links.end() && iter->first == from)
834 if(iter->second.to() == to)
844 iter = links.find(to);
845 while(iter != links.end() && iter->first == to)
847 if(iter->second.to() == from)
858 std::multimap<int, int> & links,
863 std::multimap<int, int>::iterator iter = links.find(from);
864 while(iter != links.end() && iter->first == from)
866 if(iter->second == to)
876 iter = links.find(to);
877 while(iter != links.end() && iter->first == to)
879 if(iter->second == from)
889 const std::multimap<int, Link> & links,
894 std::multimap<int, Link>::const_iterator iter = links.find(from);
895 while(iter != links.end() && iter->first == from)
897 if(iter->second.to() == to)
907 iter = links.find(to);
908 while(iter != links.end() && iter->first == to)
910 if(iter->second.to() == from)
921 const std::multimap<int, int> & links,
926 std::multimap<int, int>::const_iterator iter = links.find(from);
927 while(iter != links.end() && iter->first == from)
929 if(iter->second == to)
939 iter = links.find(to);
940 while(iter != links.end() && iter->first == to)
942 if(iter->second == from)
953 const std::multimap<int, Link> & links)
955 std::multimap<int, Link> output;
956 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
958 if(
graph::findLink(output, iter->second.from(), iter->second.to(),
true) == output.end())
960 output.insert(*iter);
967 const std::multimap<int, Link> & links,
970 std::multimap<int, Link> output;
971 for(std::multimap<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
973 if(iter->second.type() != filteredType)
975 output.insert(*iter);
982 const std::map<int, Link> & links,
985 std::map<int, Link> output;
986 for(std::map<int, Link>::const_iterator iter=links.begin(); iter!=links.end(); ++iter)
988 if(iter->second.type() != filteredType)
990 output.insert(*iter);
997 const std::map<int, Transform> & poses,
1001 float nearClipPlaneDistance,
1002 float farClipPlaneDistance,
1005 std::map<int, Transform> output;
1009 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1010 std::vector<int> ids(poses.size());
1012 cloud->resize(poses.size());
1013 ids.resize(poses.size());
1015 for(std::map<int, rtabmap::Transform>::const_iterator iter=poses.begin(); iter!=poses.end(); ++iter)
1017 if(!iter->second.isNull())
1019 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1020 ids[oi++] = iter->first;
1028 pcl::IndicesPtr(
new std::vector<int>),
1032 nearClipPlaneDistance,
1033 farClipPlaneDistance,
1037 for(
unsigned int i=0; i<indices->size(); ++i)
1039 output.insert(*poses.find(ids[indices->at(i)]));
1046 const std::map<int, Transform> & poses,
1051 if(poses.size() > 2 && radius > 0.0f)
1053 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1054 cloud->resize(poses.size());
1056 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter, ++i)
1058 (*cloud)[i] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1063 std::vector<int> names =
uKeys(poses);
1064 std::vector<Transform> transforms =
uValues(poses);
1066 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1067 tree->setInputCloud(cloud);
1068 std::set<int> indicesChecked;
1069 std::set<int> indicesKept;
1071 for(
unsigned int i=0; i<cloud->size(); ++i)
1073 if(indicesChecked.find(i) == indicesChecked.end())
1076 std::vector<float> kDistances;
1077 tree->radiusSearch(cloud->at(i), radius,
kIndices, kDistances);
1079 std::set<int> cloudIndices;
1080 const Transform & currentT = transforms.at(i);
1081 Eigen::Vector3f vA = currentT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1082 for(
unsigned int j=0; j<kIndices.size(); ++j)
1084 if(indicesChecked.find(kIndices[j]) == indicesChecked.end())
1088 const Transform & checkT = transforms.at(kIndices[j]);
1090 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1091 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
1094 cloudIndices.insert(kIndices[j]);
1099 cloudIndices.insert(kIndices[j]);
1106 bool lastAdded =
false;
1107 for(std::set<int>::reverse_iterator iter = cloudIndices.rbegin(); iter!=cloudIndices.rend(); ++iter)
1111 indicesKept.insert(*iter);
1114 indicesChecked.insert(*iter);
1119 bool firstAdded =
false;
1120 for(std::set<int>::iterator iter = cloudIndices.begin(); iter!=cloudIndices.end(); ++iter)
1124 indicesKept.insert(*iter);
1127 indicesChecked.insert(*iter);
1135 UINFO(
"Cloud filtered In = %d, Out = %d", cloud->size(), indicesKept.size());
1139 std::map<int, Transform> keptPoses;
1140 for(std::set<int>::iterator iter = indicesKept.begin(); iter!=indicesKept.end(); ++iter)
1142 keptPoses.insert(std::make_pair(names.at(*iter), transforms.at(*iter)));
1146 keptPoses.insert(*poses.begin());
1147 keptPoses.insert(*poses.rbegin());
1159 std::multimap<int, int> clusters;
1160 if(poses.size() > 1 && radius > 0.0f)
1162 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1163 cloud->resize(poses.size());
1165 for(std::map<int, Transform>::const_iterator iter = poses.begin(); iter!=poses.end(); ++iter, ++i)
1167 (*cloud)[i] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1172 std::vector<int> ids =
uKeys(poses);
1173 std::vector<Transform> transforms =
uValues(poses);
1175 pcl::search::KdTree<pcl::PointXYZ>::Ptr
tree (
new pcl::search::KdTree<pcl::PointXYZ> (
false));
1176 tree->setInputCloud(cloud);
1178 for(
unsigned int i=0; i<cloud->size(); ++i)
1181 std::vector<float> kDistances;
1182 tree->radiusSearch(cloud->at(i), radius,
kIndices, kDistances);
1184 std::set<int> cloudIndices;
1185 const Transform & currentT = transforms.at(i);
1186 Eigen::Vector3f vA = currentT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1187 for(
unsigned int j=0; j<kIndices.size(); ++j)
1189 if((
int)i != kIndices[j])
1193 const Transform & checkT = transforms.at(kIndices[j]);
1195 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
1196 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
1199 clusters.insert(std::make_pair(ids[i], ids[kIndices[j]]));
1204 clusters.insert(std::make_pair(ids[i], ids[kIndices[j]]));
1214 const std::map<int, Transform> & poses,
1215 const std::multimap<int, Link> & links,
1216 std::multimap<int, int> & hyperNodes,
1217 std::multimap<int, Link> & hyperLinks)
1219 UINFO(
"Input: poses=%d links=%d", (
int)poses.size(), (int)links.size());
1221 std::map<int, int> posesToHyperNodes;
1222 std::map<int, std::multimap<int, Link> > clusterloopClosureLinks;
1225 std::multimap<int, Link> bidirectionalLoopClosureLinks;
1226 for(std::multimap<int, Link>::const_iterator jter=links.begin(); jter!=links.end(); ++jter)
1230 jter->second.userDataCompressed().empty())
1232 if(
uContains(poses, jter->second.from()) &&
1235 UASSERT_MSG(
graph::findLink(links, jter->second.to(), jter->second.from(),
false) == links.end(),
"Input links should be unique!");
1236 bidirectionalLoopClosureLinks.insert(std::make_pair(jter->second.from(), jter->second));
1242 UINFO(
"Clustering hyper nodes...");
1244 for(std::map<int, Transform>::const_reverse_iterator iter=poses.rbegin(); iter!=poses.rend(); ++iter)
1246 if(posesToHyperNodes.find(iter->first) == posesToHyperNodes.end())
1248 int hyperNodeId = iter->first;
1249 std::list<int> loopClosures;
1250 std::set<int> loopClosuresAdded;
1251 loopClosures.push_back(iter->first);
1252 std::multimap<int, Link> clusterLinks;
1253 while(loopClosures.size())
1255 int id = loopClosures.front();
1256 loopClosures.pop_front();
1258 UASSERT(posesToHyperNodes.find(
id) == posesToHyperNodes.end());
1260 posesToHyperNodes.insert(std::make_pair(
id, hyperNodeId));
1261 hyperNodes.insert(std::make_pair(hyperNodeId,
id));
1263 for(std::multimap<int, Link>::const_iterator jter=bidirectionalLoopClosureLinks.find(
id); jter!=bidirectionalLoopClosureLinks.end() && jter->first==id; ++jter)
1265 if(posesToHyperNodes.find(jter->second.to()) == posesToHyperNodes.end() &&
1266 loopClosuresAdded.find(jter->second.to()) == loopClosuresAdded.end())
1268 loopClosures.push_back(jter->second.to());
1269 loopClosuresAdded.insert(jter->second.to());
1270 clusterLinks.insert(*jter);
1271 clusterLinks.insert(std::make_pair(jter->second.to(), jter->second.inverse()));
1272 if(jter->second.from() < jter->second.to())
1274 UWARN(
"Child to Parent link? %d->%d (type=%d)",
1275 jter->second.from(),
1277 jter->second.type());
1282 UASSERT(clusterloopClosureLinks.find(hyperNodeId) == clusterloopClosureLinks.end());
1283 clusterloopClosureLinks.insert(std::make_pair(hyperNodeId, clusterLinks));
1284 UDEBUG(
"Created hyper node %d with %d children (%f%%)",
1285 hyperNodeId, (
int)loopClosuresAdded.size(), float(posesToHyperNodes.size())/
float(poses.size())*100.0
f);
1288 UINFO(
"Clustering hyper nodes... done! (%f s)", timer.ticks());
1291 UINFO(
"Creating hyper links...");
1293 for(std::multimap<int, Link>::const_reverse_iterator jter=links.rbegin(); jter!=links.rend(); ++jter)
1297 !jter->second.userDataCompressed().empty()) &&
1298 uContains(poses, jter->second.from()) &&
1301 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.from()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1302 UASSERT_MSG(
uContains(posesToHyperNodes, jter->second.to()),
uFormat(
"%d->%d (type=%d)", jter->second.from(), jter->second.to(), jter->second.type()).c_str());
1303 int hyperNodeIDFrom = posesToHyperNodes.at(jter->second.from());
1304 int hyperNodeIDTo = posesToHyperNodes.at(jter->second.to());
1307 if(hyperNodeIDFrom != hyperNodeIDTo)
1309 std::multimap<int, Link>::iterator tmpIter =
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo);
1310 if(tmpIter!=hyperLinks.end() &&
1311 hyperNodeIDFrom == jter->second.from() &&
1312 hyperNodeIDTo == jter->second.to() &&
1317 hyperLinks.erase(tmpIter);
1321 if(
graph::findLink(hyperLinks, hyperNodeIDFrom, hyperNodeIDTo) == hyperLinks.end())
1323 UASSERT(clusterloopClosureLinks.find(hyperNodeIDFrom) != clusterloopClosureLinks.end());
1324 UASSERT(clusterloopClosureLinks.find(hyperNodeIDTo) != clusterloopClosureLinks.end());
1325 std::multimap<int, Link> tmpLinks = clusterloopClosureLinks.at(hyperNodeIDFrom);
1326 tmpLinks.insert(clusterloopClosureLinks.at(hyperNodeIDTo).begin(), clusterloopClosureLinks.at(hyperNodeIDTo).end());
1327 tmpLinks.insert(std::make_pair(jter->second.from(), jter->second));
1329 std::list<int> path =
computePath(tmpLinks, hyperNodeIDFrom, hyperNodeIDTo,
false,
true);
1331 uFormat(
"path.size()=%d, hyperNodeIDFrom=%d, hyperNodeIDTo=%d",
1334 hyperNodeIDTo).c_str());
1336 if(path.size() > 10)
1338 UWARN(
"Large path! %d nodes", (
int)path.size());
1339 std::stringstream stream;
1340 for(std::list<int>::const_iterator iter=path.begin(); iter!=path.end();++iter)
1342 if(iter!=path.begin())
1349 UWARN(
"Path = [%s]", stream.str().c_str());
1353 std::list<int>::iterator iter=path.begin();
1357 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1358 UASSERT(foundIter != tmpLinks.end());
1359 Link hyperLink = foundIter->second;
1362 for(; iter!=path.end(); ++iter)
1365 std::multimap<int, Link>::const_iterator foundIter =
graph::findLink(tmpLinks, from, to,
false);
1366 UASSERT(foundIter != tmpLinks.end());
1367 hyperLink = hyperLink.merge(foundIter->second, jter->second.type());
1372 UASSERT(hyperLink.from() == hyperNodeIDFrom);
1373 UASSERT(hyperLink.to() == hyperNodeIDTo);
1374 hyperLinks.insert(std::make_pair(hyperNodeIDFrom, hyperLink));
1376 UDEBUG(
"Created hyper link %d->%d (%f%%)",
1377 hyperLink.from(), hyperLink.to(), float(i)/float(links.size())*100.0
f);
1378 if(hyperLink.transform().getNorm() > jter->second.transform().getNorm()+1)
1380 UWARN(
"Large hyper link %d->%d (%f m)! original %d->%d (%f m)",
1383 hyperLink.transform().getNorm(),
1384 jter->second.from(),
1386 jter->second.transform().getNorm());
1394 UINFO(
"Creating hyper links... done! (%f s)", timer.ticks());
1396 UINFO(
"Output: poses=%d links=%d", (
int)
uUniqueKeys(hyperNodes).size(), (
int)links.size());
1412 int id()
const {
return id_;}
1422 return pose_.getDistance(pose);
1440 typedef std::pair<int, float>
Pair;
1445 return a.second > b.second;
1451 const std::map<int, rtabmap::Transform> & poses,
1452 const std::multimap<int, int> & links,
1455 bool updateNewCosts)
1457 std::list<std::pair<int, Transform> > path;
1459 int startNode = from;
1462 std::map<int, Node> nodes;
1463 nodes.insert(std::make_pair(startNode,
Node(startNode, 0, poses.at(startNode))));
1464 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1465 std::multimap<float, int> pqmap;
1468 pqmap.insert(std::make_pair(0, startNode));
1472 pq.push(
Pair(startNode, 0));
1475 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1480 currentNode = &nodes.find(pqmap.begin()->second)->second;
1481 pqmap.erase(pqmap.begin());
1485 currentNode = &nodes.find(pq.top().first)->second;
1491 if(currentNode->
id() == endNode)
1493 while(currentNode->
id()!=startNode)
1495 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
1496 currentNode = &nodes.find(currentNode->
fromId())->second;
1498 path.push_front(std::make_pair(startNode, poses.at(startNode)));
1503 for(std::multimap<int, int>::const_iterator iter = links.find(currentNode->
id());
1504 iter!=links.end() && iter->first == currentNode->
id();
1507 std::map<int, Node>::iterator nodeIter = nodes.find(iter->second);
1508 if(nodeIter == nodes.end())
1510 std::map<int, rtabmap::Transform>::const_iterator poseIter = poses.find(iter->second);
1511 if(poseIter == poses.end())
1513 UERROR(
"Next pose %d (from %d) should be found in poses! Ignoring it!", iter->second, iter->first);
1517 Node n(iter->second, currentNode->
id(), poseIter->second);
1519 n.setDistToEnd(n.distFrom(endPose));
1521 nodes.insert(std::make_pair(iter->second, n));
1524 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
1528 pq.push(
Pair(n.id(), n.totalCost()));
1532 else if(updateNewCosts && nodeIter->second.isOpened())
1534 float newCostSoFar = currentNode->
costSoFar() + currentNode->
distFrom(nodeIter->second.pose());
1535 if(nodeIter->second.costSoFar() > newCostSoFar)
1538 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1540 if(mapIter->second == nodeIter->first)
1542 pqmap.erase(mapIter);
1543 nodeIter->second.setCostSoFar(newCostSoFar);
1544 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1557 const std::multimap<int, Link> & links,
1560 bool updateNewCosts,
1561 bool useSameCostForAllLinks)
1563 std::list<int> path;
1565 int startNode = from;
1567 std::map<int, Node> nodes;
1568 nodes.insert(std::make_pair(startNode,
Node(startNode, 0,
Transform())));
1569 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1570 std::multimap<float, int> pqmap;
1573 pqmap.insert(std::make_pair(0, startNode));
1577 pq.push(
Pair(startNode, 0));
1580 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1585 currentNode = &nodes.find(pqmap.begin()->second)->second;
1586 pqmap.erase(pqmap.begin());
1590 currentNode = &nodes.find(pq.top().first)->second;
1596 if(currentNode->
id() == endNode)
1598 while(currentNode->
id()!=startNode)
1600 path.push_front(currentNode->
id());
1601 currentNode = &nodes.find(currentNode->
fromId())->second;
1603 path.push_front(startNode);
1608 for(std::multimap<int, Link>::const_iterator iter = links.find(currentNode->
id());
1609 iter!=links.end() && iter->first == currentNode->
id();
1612 std::map<int, Node>::iterator nodeIter = nodes.find(iter->second.to());
1614 if(!useSameCostForAllLinks)
1616 cost = iter->second.transform().getNorm();
1618 if(nodeIter == nodes.end())
1623 nodes.insert(std::make_pair(iter->second.to(), n));
1626 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
1630 pq.push(
Pair(n.id(), n.totalCost()));
1633 else if(!useSameCostForAllLinks && updateNewCosts && nodeIter->second.isOpened())
1635 float newCostSoFar = currentNode->
costSoFar() + cost;
1636 if(nodeIter->second.costSoFar() > newCostSoFar)
1639 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1641 if(mapIter->second == nodeIter->first)
1643 pqmap.erase(mapIter);
1644 nodeIter->second.setCostSoFar(newCostSoFar);
1645 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1662 bool lookInDatabase,
1663 bool updateNewCosts,
1664 float linearVelocity,
1665 float angularVelocity)
1670 std::list<std::pair<int, Transform> > path;
1671 UDEBUG(
"fromId=%d, toId=%d, lookInDatabase=%d, updateNewCosts=%d, linearVelocity=%f, angularVelocity=%f",
1679 std::multimap<int, Link> allLinks;
1685 UINFO(
"getting all %d links time = %f s", (
int)allLinks.size(), t.
ticks());
1689 int startNode = fromId;
1691 std::map<int, Node> nodes;
1693 std::priority_queue<Pair, std::vector<Pair>,
Order> pq;
1694 std::multimap<float, int> pqmap;
1697 pqmap.insert(std::make_pair(0, startNode));
1701 pq.push(
Pair(startNode, 0));
1704 while((updateNewCosts && pqmap.size()) || (!updateNewCosts && pq.size()))
1709 currentNode = &nodes.find(pqmap.begin()->second)->second;
1710 pqmap.erase(pqmap.begin());
1714 currentNode = &nodes.find(pq.top().first)->second;
1720 if(currentNode->
id() == endNode)
1722 while(currentNode->
id()!=startNode)
1724 path.push_front(std::make_pair(currentNode->
id(), currentNode->
pose()));
1725 currentNode = &nodes.find(currentNode->
fromId())->second;
1727 path.push_front(std::make_pair(startNode, currentNode->
pose()));
1732 std::map<int, Link> links;
1733 if(allLinks.size() == 0)
1735 links = memory->
getLinks(currentNode->
id(), lookInDatabase);
1739 for(std::multimap<int, Link>::const_iterator iter = allLinks.lower_bound(currentNode->
id());
1740 iter!=allLinks.end() && iter->first == currentNode->
id();
1743 links.insert(std::make_pair(iter->second.to(), iter->second));
1746 for(std::map<int, Link>::const_iterator iter = links.begin(); iter!=links.end(); ++iter)
1748 if(iter->second.from() != iter->second.to())
1750 Transform nextPose = currentNode->
pose()*iter->second.transform();
1752 if(linearVelocity <= 0.0
f && angularVelocity <= 0.0
f)
1755 cost = iter->second.transform().
getNorm();
1759 if(linearVelocity > 0.0
f)
1761 cost += iter->second.transform().getNorm()/linearVelocity;
1763 if(angularVelocity > 0.0
f)
1765 Eigen::Vector4f v1 = Eigen::Vector4f(nextPose.
x()-currentNode->
pose().
x(), nextPose.
y()-currentNode->
pose().
y(), nextPose.
z()-currentNode->
pose().
z(), 1.0f);
1767 float angle = pcl::getAngle3D(v1, v2);
1768 cost += angle / angularVelocity;
1772 std::map<int, Node>::iterator nodeIter = nodes.find(iter->first);
1773 if(nodeIter == nodes.end())
1775 Node n(iter->second.to(), currentNode->
id(), nextPose);
1778 nodes.insert(std::make_pair(iter->second.to(), n));
1781 pqmap.insert(std::make_pair(n.totalCost(), n.id()));
1785 pq.push(
Pair(n.id(), n.totalCost()));
1788 else if(updateNewCosts && nodeIter->second.isOpened())
1790 float newCostSoFar = currentNode->
costSoFar() + cost;
1791 if(nodeIter->second.costSoFar() > newCostSoFar)
1794 nodeIter->second.setPose(nextPose);
1797 for(std::multimap<float, int>::iterator mapIter=pqmap.begin(); mapIter!=pqmap.end(); ++mapIter)
1799 if(mapIter->second == nodeIter->first)
1801 pqmap.erase(mapIter);
1802 nodeIter->second.setCostSoFar(newCostSoFar);
1803 pqmap.insert(std::make_pair(nodeIter->second.totalCost(), nodeIter->first));
1816 std::stringstream stream;
1818 std::list<std::pair<int, Transform> >::const_iterator previousIter = path.end();
1820 for(std::list<std::pair<int, Transform> >::const_iterator iter=path.begin(); iter!=path.end();++iter)
1822 if(iter!=path.begin())
1827 if(previousIter!=path.end())
1832 std::multimap<int, Link>::iterator jter =
graph::findLink(allLinks, previousIter->first, iter->first);
1833 if(jter != allLinks.end())
1843 ++linkTypes[jter->second.type()];
1844 stream <<
"[" << jter->second.type() <<
"]";
1845 length += jter->second.transform().getNorm();
1850 stream << iter->first;
1854 UDEBUG(
"Path (%f m) = [%s]", length, stream.str().c_str());
1855 std::stringstream streamB;
1856 for(
unsigned int i=0; i<linkTypes.size(); ++i)
1862 streamB << i <<
"=" << linkTypes[i];
1864 UDEBUG(
"Link types = %s", streamB.str().c_str());
1871 const std::map<int, rtabmap::Transform> & nodes,
1876 if(nearestNodes.size())
1878 id = nearestNodes[0];
1884 const std::map<int, rtabmap::Transform> & nodes,
1888 std::vector<int> nearestIds;
1889 if(nodes.size() && !targetPose.
isNull())
1891 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1892 cloud->resize(nodes.size());
1893 std::vector<int> ids(nodes.size());
1895 for(std::map<int, Transform>::const_iterator iter = nodes.begin(); iter!=nodes.end(); ++iter)
1897 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1898 ids[oi++] = iter->first;
1901 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
1902 kdTree->setInputCloud(cloud);
1903 std::vector<int> ind;
1904 std::vector<float> dist;
1905 pcl::PointXYZ pt(targetPose.
x(), targetPose.
y(), targetPose.
z());
1906 kdTree->nearestKSearch(pt, k, ind, dist);
1908 nearestIds.resize(ind.size());
1909 for(
unsigned int i=0; i<ind.size(); ++i)
1911 nearestIds[i] = ids[ind[i]];
1920 const std::map<int, Transform> & nodes,
1924 std::map<int, float> foundNodes;
1925 if(nodes.size() <= 1)
1930 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1931 cloud->resize(nodes.size());
1932 std::vector<int> ids(nodes.size());
1934 for(std::map<int, Transform>::const_iterator iter = nodes.begin(); iter!=nodes.end(); ++iter)
1936 if(iter->first != nodeId)
1938 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1940 ids[oi] = iter->first;
1951 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
1952 kdTree->setInputCloud(cloud);
1953 std::vector<int> ind;
1954 std::vector<float> sqrdDist;
1955 pcl::PointXYZ pt(fromT.
x(), fromT.
y(), fromT.
z());
1956 kdTree->radiusSearch(pt, radius, ind, sqrdDist, 0);
1957 for(
unsigned int i=0; i<ind.size(); ++i)
1961 foundNodes.insert(std::make_pair(ids[ind[i]], sqrdDist[i]));
1965 UDEBUG(
"found nodes=%d", (
int)foundNodes.size());
1972 const std::map<int, Transform> & nodes,
1977 std::map<int, Transform> foundNodes;
1978 if(nodes.size() <= 1)
1983 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(
new pcl::PointCloud<pcl::PointXYZ>);
1984 cloud->resize(nodes.size());
1985 std::vector<int> ids(nodes.size());
1987 for(std::map<int, Transform>::const_iterator iter = nodes.begin(); iter!=nodes.end(); ++iter)
1989 if(iter->first != nodeId)
1991 (*cloud)[oi] = pcl::PointXYZ(iter->second.x(), iter->second.y(), iter->second.z());
1993 ids[oi] = iter->first;
2004 pcl::search::KdTree<pcl::PointXYZ>::Ptr kdTree(
new pcl::search::KdTree<pcl::PointXYZ>);
2005 kdTree->setInputCloud(cloud);
2006 std::vector<int> ind;
2007 std::vector<float> sqrdDist;
2008 pcl::PointXYZ pt(fromT.
x(), fromT.
y(), fromT.
z());
2009 kdTree->radiusSearch(pt, radius, ind, sqrdDist, 0);
2011 Eigen::Vector3f vA = fromT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
2013 for(
unsigned int i=0; i<ind.size(); ++i)
2019 const Transform & checkT = nodes.at(ids[ind[i]]);
2021 Eigen::Vector3f vB = checkT.
toEigen3f().linear()*Eigen::Vector3f(1,0,0);
2022 double a = pcl::getAngle3D(Eigen::Vector4f(vA[0], vA[1], vA[2], 0), Eigen::Vector4f(vB[0], vB[1], vB[2], 0));
2025 foundNodes.insert(std::make_pair(ids[ind[i]], nodes.at(ids[ind[i]])));
2030 foundNodes.insert(std::make_pair(ids[ind[i]], nodes.at(ids[ind[i]])));
2035 UDEBUG(
"found nodes=%d", (
int)foundNodes.size());
2040 const std::vector<std::pair<int, Transform> > & path,
2041 unsigned int fromIndex,
2042 unsigned int toIndex)
2047 UASSERT(fromIndex < path.size() && toIndex < path.size() && fromIndex <= toIndex);
2048 if(fromIndex >= toIndex)
2050 toIndex = (
unsigned int)path.size()-1;
2052 float x=0, y=0, z=0;
2053 for(
unsigned int i=fromIndex; i<toIndex-1; ++i)
2055 x += fabs(path[i].second.x() - path[i+1].second.x());
2056 y += fabs(path[i].second.y() - path[i+1].second.y());
2057 z += fabs(path[i].second.z() - path[i+1].second.z());
2059 length =
sqrt(x*x + y*y + z*z);
2065 const std::map<int, Transform> & path)
2070 float x=0, y=0, z=0;
2071 std::map<int, Transform>::const_iterator iter=path.begin();
2074 for(; iter!=path.end(); ++iter)
2076 const Transform & currentPose = iter->second;
2077 x += fabs(previousPose.
x() - currentPose.
x());
2078 y += fabs(previousPose.
y() - currentPose.
y());
2079 z += fabs(previousPose.
z() - currentPose.
z());
2080 previousPose = currentPose;
2082 length =
sqrt(x*x + y*y + z*z);
2089 std::map<int, Transform> poses,
2090 const std::multimap<int, Link> & links)
2092 std::list<std::map<int, Transform> > paths;
2093 if(poses.size() && links.size())
2098 std::map<int, Transform> path;
2099 for(std::map<int, Transform>::iterator iter=poses.begin(); iter!=poses.end();)
2101 std::multimap<int, Link>::const_iterator jter =
findLink(links, path.rbegin()->first, iter->first);
2105 poses.erase(iter++);
2113 paths.push_back(path);
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)
Transform RTABMAP_EXP transformFromXYZCorrespondencesSVD(const pcl::PointCloud< pcl::PointXYZ > &cloud1, const pcl::PointCloud< pcl::PointXYZ > &cloud2)
std::map< int, Transform > RTABMAP_EXP getPosesInRadius(int nodeId, const std::map< int, Transform > &nodes, float radius, float angle=0.0f)
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 >(), bool g2oRobust=false)
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)
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)
std::map< int, Link > getLinks(int signatureId, bool lookInDatabase=false) 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)
float UTILITE_EXP uStr2Float(const std::string &str)
std::vector< int > RTABMAP_EXP findNearestNodes(const std::map< int, rtabmap::Transform > &nodes, const rtabmap::Transform &targetPose, int k)
Basic mathematics functions.
GLM_FUNC_DECL T angle(detail::tquat< T, P > const &x)
rtabmap::Transform pose() const
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)
std::list< std::string > uSplit(const std::string &str, char separator= ' ')
#define UASSERT(condition)
Wrappers of STL for convenient functions.
static bool saveGraph(const std::string &fileName, const std::map< int, Transform > &poses, const std::multimap< int, Link > &edgeConstraints, bool useRobustConstraints=false)
std::string uJoin(const std::list< std::string > &strings, const std::string &separator="")
Node(int id, int fromId, const rtabmap::Transform &pose)
#define UASSERT_MSG(condition, msg_str)
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)
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)
int RTABMAP_EXP findNearestNode(const std::map< int, rtabmap::Transform > &nodes, const rtabmap::Transform &targetPose)
float distFrom(const rtabmap::Transform &pose) const
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)
std::vector< V > uListToVector(const std::list< V > &list)
int32_t lastFrameFromSegmentLength(std::vector< float > &dist, int32_t first_frame, float len)
bool operator()(Pair const &a, Pair const &b) const
std::vector< V > uValues(const std::multimap< K, V > &mm)
std::pair< int, float > Pair
cv::Point3d toENU_WGS84(const GeodeticCoords &origin) const
std::map< int, float > RTABMAP_EXP getNodesInRadius(int nodeId, const std::map< int, Transform > &nodes, float radius)
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
std::multimap< int, Link >::iterator RTABMAP_EXP findLink(std::multimap< int, Link > &links, int from, int to, bool checkBothWays=true)
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)
std::multimap< int, Link > getAllLinks(bool lookInDatabase, bool ignoreNullLinks=true) const
static const GLushort kIndices[]
static 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::multimap< int, Link > RTABMAP_EXP filterLinks(const std::multimap< int, Link > &links, Link::Type filteredType)
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)