10 #ifndef CLOOPCLOSERERD_IMPL_H 11 #define CLOOPCLOSERERD_IMPL_H 22 template <
class GRAPH_T>
24 : m_visualize_curr_node_covariance(false),
25 m_curr_node_covariance_color(160, 160, 160, 255),
26 m_partitions_full_update(false),
27 m_is_first_time_node_reg(true),
28 m_dijkstra_node_count_thresh(3)
30 this->initializeLoggers(
"CLoopCloserERD");
36 template <
class GRAPH_T>
43 for (
auto it = m_node_optimal_paths.begin();
44 it != m_node_optimal_paths.end(); ++it)
53 template <
class GRAPH_T>
61 this->m_time_logger.enter(
"updateState");
73 getObservation<CObservation2DRangeScan>(observations, observation);
76 m_last_laser_scan2D = scan;
80 if (!m_first_laser_scan)
82 m_first_laser_scan = m_last_laser_scan2D;
86 size_t num_registered =
87 absDiff(this->m_last_total_num_nodes, this->m_graph->nodeCount());
88 bool registered_new_node = num_registered > 0;
90 if (registered_new_node)
93 registered_new_node =
true;
97 if (!this->m_override_registered_nodes_check)
99 if (!((num_registered == 1) ^
100 (num_registered == 2 && m_is_first_time_node_reg)))
103 "Invalid number of registered nodes since last call to " 106 << num_registered <<
"\" new nodes.");
117 if (m_is_first_time_node_reg)
120 "Assigning first laserScan to the graph root node.");
121 this->m_nodes_to_laser_scans2D[this->m_graph->root] =
123 m_is_first_time_node_reg =
false;
127 this->m_nodes_to_laser_scans2D[this->m_graph->nodeCount() - 1] =
130 if (m_laser_params.use_scan_matching)
133 this->addScanMatchingEdges(this->m_graph->nodeCount() - 1);
137 m_partitions_full_update =
138 ((this->m_graph->nodeCount() %
139 m_lc_params.full_partition_per_nodes) == 0 ||
140 this->m_just_inserted_lc)
143 this->updateMapPartitions(
144 m_partitions_full_update,
145 num_registered == 2);
149 this->checkPartitionsForLC(&partitions_for_LC);
150 this->evaluatePartitionsForLC(partitions_for_LC);
152 if (m_visualize_curr_node_covariance)
154 this->execDijkstraProjection();
157 this->m_last_total_num_nodes = this->m_graph->nodeCount();
160 this->m_time_logger.leave(
"updateState");
165 template <
class GRAPH_T>
168 std::set<mrpt::graphs::TNodeID>* nodes_set)
174 int fetched_nodeIDs = 0;
175 for (
int nodeID_i = static_cast<int>(curr_nodeID) - 1;
176 ((fetched_nodeIDs <= this->m_laser_params.prev_nodes_for_ICP) &&
181 nodes_set->insert(nodeID_i);
186 template <
class GRAPH_T>
192 using namespace mrpt;
200 std::set<TNodeID> nodes_set;
201 this->fetchNodeIDsForScanMatching(curr_nodeID, &nodes_set);
205 node_it != nodes_set.end(); ++node_it)
211 "Fetching laser scan for nodes: " << *node_it <<
"==> " 215 this->getICPEdge(*node_it, curr_nodeID, &rel_edge, &icp_info);
216 if (!found_edge)
continue;
223 m_laser_params.goodness_threshold_win.addNewMeasurement(
226 double goodness_thresh =
227 m_laser_params.goodness_threshold_win.getMedian() *
228 m_consec_icp_constraint_factor;
229 bool accept_goodness = icp_info.
goodness > goodness_thresh;
231 "Curr. Goodness: " << icp_info.
goodness 232 <<
"|\t Threshold: " << goodness_thresh <<
" => " 233 << (accept_goodness ?
"ACCEPT" :
"REJECT"));
237 bool accept_mahal_distance = this->mahalanobisDistanceOdometryToICPEdge(
238 *node_it, curr_nodeID, rel_edge);
241 if (accept_goodness && accept_mahal_distance)
243 this->registerNewEdge(*node_it, curr_nodeID, rel_edge);
249 template <
class GRAPH_T>
257 this->m_time_logger.enter(
"getICPEdge");
274 "TGetICPEdgeAdParams:\n" 281 bool from_success = this->getPropsOfNodeID(
282 from, &from_pose, from_scan, from_params);
285 bool to_success = this->getPropsOfNodeID(to, &to_pose, to_scan, to_params);
287 if (!from_success || !to_success)
291 << from <<
" or node #" << to
292 <<
" doesn't contain a valid LaserScan. Ignoring this...");
305 initial_estim = to_pose - from_pose;
309 "from_pose: " << from_pose <<
"| to_pose: " << to_pose
310 <<
"| init_estim: " << initial_estim);
312 range_ops_t::getICPEdge(
313 *from_scan, *to_scan, rel_edge, &initial_estim, icp_info);
316 this->m_time_logger.leave(
"getICPEdge");
321 template <
class GRAPH_T>
324 const std::map<mrpt::graphs::TNodeID, node_props_t>& group_params,
336 search = group_params.find(nodeID);
338 if (search == group_params.end())
344 *node_props = search->second;
354 template <
class GRAPH_T>
363 bool filled_pose =
false;
364 bool filled_scan =
false;
371 *pose = node_props->
pose;
375 if (node_props->
scan)
377 scan = node_props->
scan;
384 !(filled_pose ^ filled_scan),
386 "Either BOTH or NONE of the filled_pose, filled_scan should be set." 388 static_cast<unsigned long>(nodeID)));
397 this->m_graph->nodes.find(nodeID);
398 if (search != this->m_graph->nodes.end())
400 *pose = search->second;
411 this->m_nodes_to_laser_scans2D.find(nodeID);
412 if (search != this->m_nodes_to_laser_scans2D.end())
414 scan = search->second;
419 return filled_pose && filled_scan;
422 template <
class GRAPH_T>
427 this->m_time_logger.enter(
"LoopClosureEvaluation");
430 using namespace mrpt;
433 partitions_for_LC->clear();
437 map<int, std::vector<uint32_t>>
::iterator finder;
439 if (m_partitions_full_update)
441 m_partitionID_to_prev_nodes_list.clear();
447 partitions_it != m_curr_partitions.end();
448 ++partitions_it, ++partitionID)
452 if (m_lc_params.LC_check_curr_partition_only)
454 bool curr_node_in_curr_partition =
456 partitions_it->begin(), partitions_it->end(),
457 this->m_graph->nodeCount() - 1)) != partitions_it->end());
458 if (!curr_node_in_curr_partition)
465 finder = m_partitionID_to_prev_nodes_list.find(partitionID);
466 if (finder == m_partitionID_to_prev_nodes_list.end())
469 m_partitionID_to_prev_nodes_list.insert(
470 make_pair(partitionID, *partitions_it));
474 if (*partitions_it == finder->second)
484 finder->second = *partitions_it;
489 int curr_node_index = 1;
490 size_t prev_nodeID = *(partitions_it->begin());
492 it = partitions_it->begin() + 1;
493 it != partitions_it->end(); ++it, ++curr_node_index)
495 size_t curr_nodeID = *it;
499 if ((curr_nodeID - prev_nodeID) > m_lc_params.LC_min_nodeid_diff)
503 int num_after_nodes = partitions_it->size() - curr_node_index;
504 int num_before_nodes = partitions_it->size() - num_after_nodes;
505 if (num_after_nodes >= m_lc_params.LC_min_remote_nodes &&
506 num_before_nodes >= m_lc_params.LC_min_remote_nodes)
509 "Found potential loop closures:" 511 <<
"\tPartitionID: " << partitionID << endl
517 <<
"\t" << prev_nodeID <<
" ==> " << curr_nodeID << endl
518 <<
"\tNumber of LC nodes: " << num_after_nodes);
519 partitions_for_LC->push_back(*partitions_it);
526 prev_nodeID = curr_nodeID;
529 "Successfully checked partition: " << partitionID);
532 this->m_time_logger.leave(
"LoopClosureEvaluation");
536 template <
class GRAPH_T>
541 using namespace mrpt;
545 this->m_time_logger.enter(
"LoopClosureEvaluation");
547 if (partitions.size() == 0)
return;
550 "Evaluating partitions for loop closures...\n%s\n",
551 this->header_sep.c_str());
555 p_it != partitions.end(); ++p_it)
557 std::vector<uint32_t> partition(*p_it);
560 std::vector<uint32_t> groupA, groupB;
561 this->splitPartitionToGroups(
562 partition, &groupA, &groupB,
567 this->generateHypotsPool(groupA, groupB, &hypots_pool);
570 CMatrixDouble consist_matrix(hypots_pool.size(), hypots_pool.size());
571 this->generatePWConsistenciesMatrix(
572 groupA, groupB, hypots_pool, &consist_matrix);
576 this->evalPWConsistenciesMatrix(
577 consist_matrix, hypots_pool, &valid_hypots);
580 if (valid_hypots.size())
584 it != valid_hypots.end(); ++it)
586 this->registerHypothesis(**it);
592 it != hypots_pool.end(); ++it)
599 this->m_time_logger.leave(
"LoopClosureEvaluation");
604 template <
class GRAPH_T>
614 valid_hypots->clear();
619 bool valid_lambda_ratio = this->computeDominantEigenVector(
622 if (!valid_lambda_ratio)
return;
630 double dot_product = 0;
631 for (
int i = 0; i !=
w.size(); ++i)
638 double potential_dot_product =
639 ((
w.transpose() * u) /
w.squaredNorm()).
value();
641 "current: %f | potential_dot_product: %f", dot_product,
642 potential_dot_product);
643 if (potential_dot_product > dot_product)
646 dot_product = potential_dot_product;
656 cout <<
"Outcome of discretization: " <<
w.transpose() << endl;
662 for (
int wi = 0; wi !=
w.size(); ++wi)
669 valid_hypots->push_back(this->findHypotByID(hypots_pool, wi));
678 template <
class GRAPH_T>
680 std::vector<uint32_t>& partition, std::vector<uint32_t>* groupA,
681 std::vector<uint32_t>* groupB,
int max_nodes_in_group )
685 using namespace mrpt;
693 max_nodes_in_group == -1 || max_nodes_in_group > 0,
695 "Value %d not permitted for max_nodes_in_group" 696 "Either use a positive integer, " 697 "or -1 for non-restrictive partition size",
698 max_nodes_in_group));
703 size_t index_to_split = 1;
705 it != partition.end(); ++it, ++index_to_split)
709 if ((curr_nodeID - prev_nodeID) > m_lc_params.LC_min_nodeid_diff)
714 prev_nodeID = curr_nodeID;
716 ASSERTDEB_(partition.size() > index_to_split);
719 *groupA = std::vector<uint32_t>(
720 partition.begin(), partition.begin() + index_to_split);
721 *groupB = std::vector<uint32_t>(
722 partition.begin() + index_to_split, partition.end());
724 if (max_nodes_in_group != -1)
727 if (groupA->size() >
static_cast<size_t>(max_nodes_in_group))
729 *groupA = std::vector<uint32_t>(
730 groupA->begin(), groupA->begin() + max_nodes_in_group);
733 if (groupB->size() >
static_cast<size_t>(max_nodes_in_group))
735 *groupB = std::vector<uint32_t>(
736 groupB->end() - max_nodes_in_group, groupB->end());
744 template <
class GRAPH_T>
746 const std::vector<uint32_t>& groupA,
const std::vector<uint32_t>& groupB,
751 using namespace mrpt;
756 "generateHypotsPool: Given hypotsp_t pointer is invalid.");
757 generated_hypots->clear();
762 <<
" - size: " << groupA.size() << endl);
765 <<
" - size: " << groupB.size() << endl);
779 size_t nodes_count = groupA.size();
783 nodes_count ==
params.size(),
785 "Size mismatch between nodeIDs in group [%lu]" 786 " and corresponding properties map [%lu]",
787 nodes_count,
params.size()));
793 int hypot_counter = 0;
794 int invalid_hypots = 0;
798 b_it = groupB.begin();
799 b_it != groupB.end(); ++b_it)
802 a_it = groupA.begin();
803 a_it != groupA.end(); ++a_it)
812 hypot->id = hypot_counter++;
827 fillNodePropsFromGroupParams(
831 fillNodePropsFromGroupParams(
853 bool found_edge = this->getICPEdge(
854 *b_it, *a_it, &edge, &icp_info, icp_ad_params);
856 hypot->setEdge(edge);
863 double goodness_thresh =
864 m_laser_params.goodness_threshold_win.getMedian() *
865 m_lc_icp_constraint_factor;
866 bool accept_goodness = icp_info.
goodness > goodness_thresh;
868 "generateHypotsPool:\nCurr. Goodness: " 869 << icp_info.
goodness <<
"|\t Threshold: " << goodness_thresh
870 <<
" => " << (accept_goodness ?
"ACCEPT" :
"REJECT")
873 if (!found_edge || !accept_goodness)
875 hypot->is_valid =
false;
878 generated_hypots->push_back(hypot);
884 delete icp_ad_params;
888 "Generated pool of hypotheses...\tsize = " 889 << generated_hypots->size()
890 <<
"\tinvalid hypotheses: " << invalid_hypots);
897 template <
class GRAPH_T>
903 using namespace mrpt;
908 this->m_time_logger.enter(
"DominantEigenvectorComputation");
910 double lambda1, lambda2;
911 bool is_valid_lambda_ratio =
false;
913 if (use_power_method)
916 "\nPower method for computing the first two " 917 "eigenvectors/eigenvalues hasn't been implemented yet\n");
922 consist_matrix.eigenVectors(eigvecs, eigvals);
928 eigvecs.size() == eigvals.size() &&
929 consist_matrix.size() == eigvals.size(),
931 "Size of eigvecs \"%lu\"," 933 "consist_matrix \"%lu\" don't match",
934 static_cast<unsigned long>(eigvecs.size()),
935 static_cast<unsigned long>(eigvals.size()),
936 static_cast<unsigned long>(consist_matrix.size())));
938 eigvecs.extractCol(eigvecs.cols() - 1, *eigvec);
939 lambda1 = eigvals(eigvals.rows() - 1, eigvals.cols() - 1);
940 lambda2 = eigvals(eigvals.rows() - 2, eigvals.cols() - 2);
944 for (
int i = 0; i != eigvec->size(); ++i)
946 (*eigvec)(i) = abs((*eigvec)(i));
954 "Bad lambda2 value: " 955 << lambda2 <<
" => Skipping current evaluation." << endl);
958 double curr_lambda_ratio = lambda1 / lambda2;
960 "lambda1 = " << lambda1 <<
" | lambda2 = " << lambda2
961 <<
"| ratio = " << curr_lambda_ratio << endl);
963 is_valid_lambda_ratio =
964 (curr_lambda_ratio > m_lc_params.LC_eigenvalues_ratio_thresh);
966 this->m_time_logger.leave(
"DominantEigenvectorComputation");
967 return is_valid_lambda_ratio;
972 template <
class GRAPH_T>
974 const std::vector<uint32_t>& groupA,
const std::vector<uint32_t>& groupB,
976 const paths_t* groupA_opt_paths ,
977 const paths_t* groupB_opt_paths )
981 using namespace mrpt;
988 consist_matrix,
"Invalid pointer to the Consistency matrix is given");
990 static_cast<unsigned long>(consist_matrix->rows()) ==
991 hypots_pool.size() &&
992 static_cast<unsigned long>(consist_matrix->rows()) ==
994 "Consistency matrix dimensions aren't equal to the hypotheses pool " 998 ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" 1000 <<
"In generatePWConsistencyMatrix:\n" 1003 <<
"\tHypots pool Size: " << hypots_pool.size());
1007 b1_it != groupB.end(); ++b1_it)
1013 b2_it != groupB.end(); ++b2_it)
1019 a1_it != groupA.end(); ++a1_it)
1023 this->findHypotByEnds(hypots_pool,
b2,
a1);
1029 a2_it != groupA.end(); ++a2_it)
1033 this->findHypotByEnds(hypots_pool,
b1,
a2);
1040 if (hypot_b2_a1->is_valid && hypot_b1_a2->is_valid)
1046 extracted_hypots.push_back(hypot_b2_a1);
1047 extracted_hypots.push_back(hypot_b1_a2);
1049 paths_t* curr_opt_paths = NULL;
1050 if (groupA_opt_paths || groupB_opt_paths)
1052 curr_opt_paths =
new paths_t();
1059 if (groupA_opt_paths)
1061 const path_t*
p = this->findPathByEnds(
1062 *groupA_opt_paths,
a1,
a2,
1064 curr_opt_paths->push_back(*
p);
1068 curr_opt_paths->push_back(
path_t());
1071 if (groupB_opt_paths)
1073 const path_t*
p = this->findPathByEnds(
1074 *groupB_opt_paths,
b1,
b2,
1076 curr_opt_paths->push_back(*
p);
1080 curr_opt_paths->push_back(
path_t());
1084 consistency = this->generatePWConsistencyElement(
1085 a1,
a2,
b1,
b2, extracted_hypots, curr_opt_paths);
1087 delete curr_opt_paths;
1102 int id1 = hypot_b2_a1->id;
1103 int id2 = hypot_b1_a2->id;
1105 (*consist_matrix)(id1, id2) = consistency;
1106 (*consist_matrix)(id2, id1) = consistency;
1123 template <
class GRAPH_T>
1130 using namespace std;
1131 using namespace mrpt;
1159 const path_t* path_a1_a2;
1160 if (!opt_paths || opt_paths->begin()->isEmpty())
1163 "Running dijkstra [a1] " <<
a1 <<
" => [a2] " <<
a2);
1164 execDijkstraProjection(
a1,
a2);
1165 path_a1_a2 = this->queryOptimalPath(
a2);
1170 path_a1_a2 = &(*opt_paths->begin());
1176 const path_t* path_b1_b2;
1177 if (!opt_paths || opt_paths->rend()->isEmpty())
1180 "Running djkstra [b1] " <<
b1 <<
" => [b2] " <<
b2);
1181 execDijkstraProjection(
b1,
b2);
1182 path_b1_b2 = this->queryOptimalPath(
b2);
1186 path_b1_b2 = &(*opt_paths->rbegin());
1194 hypot_t* hypot_b1_a2 = this->findHypotByEnds(hypots,
b1,
a2);
1196 hypot_t* hypot_b2_a1 = this->findHypotByEnds(hypots,
b2,
a1);
1201 res_transform += hypot_b1_a2->getInverseEdge();
1203 res_transform += hypot_b2_a1->getEdge();
1206 "\n-----------Resulting Transformation----------- Hypots: #" 1207 << hypot_b1_a2->id <<
", #" << hypot_b2_a1->id << endl
1208 <<
"a1 --> a2 => b1 --> b2 => a1: " <<
a1 <<
" --> " <<
a2 <<
" => " 1209 <<
b1 <<
" --> " <<
b2 <<
" => " <<
a1 << endl
1210 << res_transform << endl
1212 <<
"DIJKSTRA: " <<
a1 <<
" --> " <<
a2 <<
": " 1214 <<
"DIJKSTRA: " <<
b1 <<
" --> " <<
b2 <<
": " 1216 <<
"hypot_b1_a2(inv):\n" 1217 << hypot_b1_a2->getInverseEdge() << endl
1219 << hypot_b2_a1->getEdge() << endl);
1223 res_transform.getMeanVal().getAsVector(T);
1227 res_transform.getCovariance(cov_mat);
1233 double exponent = (-T.transpose() * cov_mat * T).
value();
1234 double consistency_elem = exp(exponent);
1241 return consistency_elem;
1245 template <
class GRAPH_T>
1251 using namespace mrpt;
1257 cit != vec_paths.end(); ++cit)
1259 if (cit->getSource() ==
src && cit->getDestination() ==
dst)
1265 if (throw_exc && !
res)
1269 "Path for %lu => %lu is not found. Exiting...\n",
1270 static_cast<unsigned long>(
src),
1271 static_cast<unsigned long>(
dst)));
1277 template <
class GRAPH_T>
1284 using namespace std;
1287 v_cit != vec_hypots.end(); v_cit++)
1289 if ((*v_cit)->hasEnds(from, to))
1308 template <
class GRAPH_T>
1311 const hypotsp_t& vec_hypots,
const size_t&
id,
bool throw_exc )
1316 v_cit != vec_hypots.end(); v_cit++)
1318 if ((*v_cit)->id ==
id)
1335 template <
class GRAPH_T>
1341 using namespace std;
1342 using namespace mrpt;
1350 this->m_time_logger.enter(
"Dijkstra Projection");
1352 "----------- Done with Dijkstra Projection... ----------";
1358 (ending_node >= 0 && ending_node < this->m_graph->nodeCount()));
1360 starting_node != ending_node,
"Starting and Ending nodes coincede");
1363 stringstream ss_debug(
"");
1364 ss_debug <<
"Executing Dijkstra Projection: " << starting_node <<
" => ";
1367 ss_debug <<
"..." << endl;
1371 ss_debug << ending_node << endl;
1374 if (this->m_graph->nodeCount() < m_dijkstra_node_count_thresh)
1380 std::vector<bool> visited_nodes(this->m_graph->nodeCount(),
false);
1381 m_node_optimal_paths.clear();
1384 std::map<TNodeID, std::set<TNodeID>> neighbors_of;
1385 this->m_graph->getAdjacencyMatrix(neighbors_of);
1390 std::set<path_t*> pool_of_paths;
1392 std::set<TNodeID> starting_node_neighbors(neighbors_of.at(starting_node));
1394 starting_node_neighbors.begin();
1395 n_it != starting_node_neighbors.end(); ++n_it)
1398 this->getMinUncertaintyPath(
1399 starting_node, *n_it, path_between_neighbors);
1401 pool_of_paths.insert(path_between_neighbors);
1404 visited_nodes.at(starting_node) =
true;
1422 it != visited_nodes.end(); ++it)
1435 if (visited_nodes.at(ending_node))
1438 this->m_time_logger.leave(
"Dijkstra Projection");
1443 path_t* optimal_path = this->popMinUncertaintyPath(&pool_of_paths);
1468 if (!visited_nodes.at(dest))
1470 m_node_optimal_paths[dest] = optimal_path;
1471 visited_nodes.at(dest) =
true;
1477 &pool_of_paths, *optimal_path, neighbors_of.at(dest));
1482 this->m_time_logger.leave(
"Dijkstra Projection");
1486 template <
class GRAPH_T>
1488 std::set<path_t*>* pool_of_paths,
const path_t& current_path,
1489 const std::set<mrpt::graphs::TNodeID>& neighbors)
const 1492 using namespace std;
1504 neigh_it != neighbors.end(); ++neigh_it)
1506 if (*neigh_it == second_to_last_node)
continue;
1509 path_t path_between_nodes;
1510 this->getMinUncertaintyPath(
1511 node_to_append_from, *neigh_it, &path_between_nodes);
1515 *path_to_append = current_path;
1516 *path_to_append += path_between_nodes;
1518 pool_of_paths->insert(path_to_append);
1524 template <
class GRAPH_T>
1528 using namespace std;
1532 search = m_node_optimal_paths.find(node);
1533 if (search != m_node_optimal_paths.end())
1535 path = search->second;
1543 template <
class GRAPH_T>
1546 path_t* path_between_nodes)
const 1550 using namespace std;
1553 this->m_graph->edgeExists(from, to) ||
1554 this->m_graph->edgeExists(to, from),
1556 "\nEdge between the provided nodeIDs" 1557 "(%lu <-> %lu) does not exist\n",
1564 path_between_nodes->
clear();
1568 double curr_determinant = 0;
1570 std::pair<edges_citerator, edges_citerator> fwd_edges_pair =
1571 this->m_graph->getEdges(from, to);
1581 edges_it != fwd_edges_pair.second; ++edges_it)
1586 curr_edge.copyFrom(edges_it->second);
1590 curr_edge.getInformationMatrix(inf_mat);
1595 curr_edge.cov_inv = inf_mat;
1606 *path_between_nodes = curr_path;
1610 std::pair<edges_citerator, edges_citerator> bwd_edges_pair =
1611 this->m_graph->getEdges(to, from);
1621 edges_it != bwd_edges_pair.second; ++edges_it)
1626 (edges_it->second).
inverse(curr_edge);
1630 curr_edge.getInformationMatrix(inf_mat);
1635 curr_edge.cov_inv = inf_mat;
1646 *path_between_nodes = curr_path;
1653 template <
class GRAPH_T>
1655 typename std::set<path_t*>* pool_of_paths)
const 1658 using namespace std;
1661 path_t* optimal_path = NULL;
1662 double curr_determinant = 0;
1664 it != pool_of_paths->end(); ++it)
1669 if (curr_determinant < (*it)->getDeterminant())
1677 pool_of_paths->erase(optimal_path);
1679 return optimal_path;
1683 template <
class GRAPH_T>
1690 using namespace std;
1695 this->m_graph->nodes.at(to) - this->m_graph->nodes.at(from);
1697 (rel_edge.getMeanVal() - initial_estim).getAsVector(mean_diff);
1701 rel_edge.getCovariance(cov_mat);
1704 double mahal_distance =
1706 bool mahal_distance_null = std::isnan(mahal_distance);
1707 if (!mahal_distance_null)
1709 m_laser_params.mahal_distance_ICP_odom_win.addNewMeasurement(
1716 m_laser_params.mahal_distance_ICP_odom_win.getMedian() * 4;
1718 (threshold >= mahal_distance && !mahal_distance_null) ?
true :
false;
1730 template <
class GRAPH_T>
1735 this->registerNewEdge(hypot.from, hypot.to, hypot.getEdge());
1738 template <
class GRAPH_T>
1745 using namespace std;
1746 parent_t::registerNewEdge(from, to, rel_edge);
1749 m_edge_types_to_nums[
"ICP2D"]++;
1752 if (
absDiff(to, from) > m_lc_params.LC_min_nodeid_diff)
1754 m_edge_types_to_nums[
"LC"]++;
1755 this->m_just_inserted_lc =
true;
1760 this->m_just_inserted_lc =
false;
1764 this->m_graph->insertEdge(from, to, rel_edge);
1769 template <
class GRAPH_T>
1774 parent_t::setWindowManagerPtr(win_manager);
1777 if (this->m_win_manager)
1779 if (this->m_win_observer)
1781 this->m_win_observer->registerKeystroke(
1782 m_laser_params.keystroke_laser_scans,
1783 "Toggle LaserScans Visualization");
1784 this->m_win_observer->registerKeystroke(
1785 m_lc_params.keystroke_map_partitions,
1786 "Toggle Map Partitions Visualization");
1790 "Fetched the window manager, window observer successfully.");
1793 template <
class GRAPH_T>
1795 const std::map<std::string, bool>& events_occurred)
1798 parent_t::notifyOfWindowEvents(events_occurred);
1801 if (events_occurred.at(m_laser_params.keystroke_laser_scans))
1803 this->toggleLaserScansVisualization();
1806 if (events_occurred.at(m_lc_params.keystroke_map_partitions))
1808 this->toggleMapPartitionsVisualization();
1814 template <
class GRAPH_T>
1817 using namespace mrpt;
1823 this->m_win_manager->assignTextMessageParameters(
1824 &m_lc_params.offset_y_map_partitions,
1825 &m_lc_params.text_index_map_partitions);
1829 mrpt::make_aligned_shared<CSetOfObjects>();
1830 map_partitions_obj->setName(
"map_partitions");
1833 scene->insert(map_partitions_obj);
1834 this->m_win->unlockAccess3DScene();
1835 this->m_win->forceRepaint();
1838 template <
class GRAPH_T>
1841 using namespace mrpt;
1848 std::stringstream title;
1849 title <<
"# Partitions: " << m_curr_partitions.size();
1850 this->m_win_manager->addTextMessage(
1851 5, -m_lc_params.offset_y_map_partitions, title.str(),
1853 m_lc_params.text_index_map_partitions);
1867 int partitionID = 0;
1868 bool partition_contains_last_node =
false;
1869 bool found_last_node =
1872 "Searching for the partition of the last nodeID: " 1873 << (this->m_graph->nodeCount() - 1));
1876 p_it != m_curr_partitions.end(); ++p_it, ++partitionID)
1879 std::vector<uint32_t> nodes_list = *p_it;
1883 nodes_list.begin(), nodes_list.end(),
1884 this->m_graph->nodeCount() - 1) != nodes_list.end())
1886 partition_contains_last_node =
true;
1888 found_last_node =
true;
1892 partition_contains_last_node =
false;
1901 map_partitions_obj->getByName(partition_obj_name);
1909 if (m_lc_params.LC_check_curr_partition_only)
1911 curr_partition_obj->setVisibility(partition_contains_last_node);
1917 "\tCreating a new CSetOfObjects partition object for partition " 1920 curr_partition_obj = mrpt::make_aligned_shared<CSetOfObjects>();
1921 curr_partition_obj->setName(partition_obj_name);
1922 if (m_lc_params.LC_check_curr_partition_only)
1925 curr_partition_obj->setVisibility(partition_contains_last_node);
1930 CSphere::Ptr balloon_obj = mrpt::make_aligned_shared<CSphere>();
1931 balloon_obj->setName(balloon_obj_name);
1932 balloon_obj->setRadius(m_lc_params.balloon_radius);
1933 balloon_obj->setColor_u8(m_lc_params.balloon_std_color);
1934 balloon_obj->enableShowName();
1936 curr_partition_obj->insert(balloon_obj);
1942 mrpt::make_aligned_shared<CSetOfLines>();
1943 connecting_lines_obj->setName(
"connecting_lines");
1944 connecting_lines_obj->setColor_u8(
1945 m_lc_params.connecting_lines_color);
1946 connecting_lines_obj->setLineWidth(0.1f);
1948 curr_partition_obj->insert(connecting_lines_obj);
1953 map_partitions_obj->insert(curr_partition_obj);
1960 std::pair<double, double> centroid_coords;
1961 this->computeCentroidOfNodesVector(nodes_list, ¢roid_coords);
1964 centroid_coords.first, centroid_coords.second,
1965 m_lc_params.balloon_elevation);
1974 curr_partition_obj->getByName(balloon_obj_name);
1975 balloon_obj = std::dynamic_pointer_cast<
CSphere>(
obj);
1976 balloon_obj->setLocation(balloon_location);
1977 if (partition_contains_last_node)
1978 balloon_obj->setColor_u8(m_lc_params.balloon_curr_color);
1980 balloon_obj->setColor_u8(m_lc_params.balloon_std_color);
1993 curr_partition_obj->getByName(
"connecting_lines");
1994 connecting_lines_obj = std::dynamic_pointer_cast<
CSetOfLines>(
obj);
1996 connecting_lines_obj->clear();
1999 it != nodes_list.end(); ++it)
2001 CPose3D curr_pose(this->m_graph->nodes.at(*it));
2002 TPoint3D curr_node_location(curr_pose.asTPose());
2005 curr_node_location, balloon_location);
2006 connecting_lines_obj->appendLine(connecting_line);
2012 if (!found_last_node)
2015 THROW_EXCEPTION(
"Last inserted nodeID was not found in any partition.");
2023 size_t prev_size = m_last_partitions.size();
2024 size_t curr_size = m_curr_partitions.size();
2025 if (curr_size < prev_size)
2028 for (
size_t partitionID = curr_size; partitionID != prev_size;
2033 "partition_%lu", static_cast<unsigned long>(partitionID));
2036 map_partitions_obj->getByName(partition_obj_name);
2040 partition_obj_name.c_str())
2042 map_partitions_obj->removeObject(
obj);
2047 this->m_win->unlockAccess3DScene();
2048 this->m_win->forceRepaint();
2051 template <
class GRAPH_T>
2055 ASSERTDEBMSG_(this->m_win,
"No CDisplayWindow3D* was provided");
2056 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* was provided");
2062 if (m_lc_params.visualize_map_partitions)
2065 scene->getByName(
"map_partitions");
2066 obj->setVisibility(!
obj->isVisible());
2070 this->dumpVisibilityErrorMsg(
"visualize_map_partitions");
2073 this->m_win->unlockAccess3DScene();
2074 this->m_win->forceRepaint();
2079 template <
class GRAPH_T>
2081 const std::vector<uint32_t>& nodes_list,
2082 std::pair<double, double>* centroid_coords)
const 2088 double centroid_x = 0;
2089 double centroid_y = 0;
2091 node_it != nodes_list.end(); ++node_it)
2093 pose_t curr_node_pos = this->m_graph->nodes.at(*node_it);
2094 centroid_x += curr_node_pos.x();
2095 centroid_y += curr_node_pos.y();
2099 centroid_coords->first =
2100 centroid_x /
static_cast<double>(nodes_list.size());
2101 centroid_coords->second =
2102 centroid_y /
static_cast<double>(nodes_list.size());
2107 template <
class GRAPH_T>
2113 if (m_laser_params.visualize_laser_scans)
2116 this->m_win->get3DSceneAndLock();
2119 mrpt::make_aligned_shared<mrpt::opengl::CPlanarLaserScan>();
2120 laser_scan_viz->enablePoints(
true);
2121 laser_scan_viz->enableLine(
true);
2122 laser_scan_viz->enableSurface(
true);
2123 laser_scan_viz->setSurfaceColor(
2124 m_laser_params.laser_scans_color.R,
2125 m_laser_params.laser_scans_color.G,
2126 m_laser_params.laser_scans_color.B,
2127 m_laser_params.laser_scans_color.A);
2129 laser_scan_viz->setName(
"laser_scan_viz");
2131 scene->insert(laser_scan_viz);
2132 this->m_win->unlockAccess3DScene();
2133 this->m_win->forceRepaint();
2139 template <
class GRAPH_T>
2145 if (m_laser_params.visualize_laser_scans && m_last_laser_scan2D)
2148 this->m_win->get3DSceneAndLock();
2151 scene->getByName(
"laser_scan_viz");
2154 laser_scan_viz->setScan(*m_last_laser_scan2D);
2158 this->m_graph->nodes.find(this->m_graph->nodeCount() - 1);
2159 if (search != this->m_graph->nodes.end())
2161 laser_scan_viz->setPose(search->second);
2164 laser_scan_viz->setPose(
2166 laser_scan_viz->getPoseX(), laser_scan_viz->getPoseY(),
2172 this->m_win->unlockAccess3DScene();
2173 this->m_win->forceRepaint();
2179 template <
class GRAPH_T>
2183 ASSERTDEBMSG_(this->m_win,
"No CDisplayWindow3D* was provided");
2184 ASSERTDEBMSG_(this->m_win_manager,
"No CWindowManager* was provided");
2190 if (m_laser_params.visualize_laser_scans)
2193 scene->getByName(
"laser_scan_viz");
2194 obj->setVisibility(!
obj->isVisible());
2198 this->dumpVisibilityErrorMsg(
"visualize_laser_scans");
2201 this->m_win->unlockAccess3DScene();
2202 this->m_win->forceRepaint();
2207 template <
class GRAPH_T>
2209 std::map<std::string, int>* edge_types_to_num)
const 2212 *edge_types_to_num = m_edge_types_to_nums;
2216 template <
class GRAPH_T>
2220 parent_t::initializeVisuals();
2222 this->m_time_logger.enter(
"Visuals");
2225 m_laser_params.has_read_config,
2226 "Configuration parameters aren't loaded yet");
2227 if (m_laser_params.visualize_laser_scans)
2229 this->initLaserScansVisualization();
2231 if (m_lc_params.visualize_map_partitions)
2233 this->initMapPartitionsVisualization();
2236 if (m_visualize_curr_node_covariance)
2238 this->initCurrCovarianceVisualization();
2241 this->m_time_logger.leave(
"Visuals");
2244 template <
class GRAPH_T>
2248 parent_t::updateVisuals();
2250 this->m_time_logger.enter(
"Visuals");
2252 if (m_laser_params.visualize_laser_scans)
2254 this->updateLaserScansVisualization();
2256 if (m_lc_params.visualize_map_partitions)
2258 this->updateMapPartitionsVisualization();
2260 if (m_visualize_curr_node_covariance)
2262 this->updateCurrCovarianceVisualization();
2265 this->m_time_logger.leave(
"Visuals");
2269 template <
class GRAPH_T>
2273 using namespace std;
2277 this->m_win_manager->assignTextMessageParameters(
2278 &m_offset_y_curr_node_covariance,
2279 &m_text_index_curr_node_covariance);
2282 this->m_win_manager->addTextMessage(
2283 5, -m_offset_y_curr_node_covariance, title,
2285 m_text_index_curr_node_covariance);
2288 CEllipsoid::Ptr cov_ellipsis_obj = mrpt::make_aligned_shared<CEllipsoid>();
2289 cov_ellipsis_obj->setName(
"cov_ellipsis_obj");
2290 cov_ellipsis_obj->setColor_u8(m_curr_node_covariance_color);
2291 cov_ellipsis_obj->setLocation(0, 0, 0);
2295 scene->insert(cov_ellipsis_obj);
2296 this->m_win->unlockAccess3DScene();
2297 this->m_win->forceRepaint();
2302 template <
class GRAPH_T>
2306 using namespace std;
2313 path_t* path = queryOptimalPath(curr_node);
2318 pose_t curr_position = this->m_graph->nodes.at(curr_node);
2321 "In updateCurrCovarianceVisualization\n" 2322 "Covariance matrix:\n" 2333 cov_ellipsis_obj->setLocation(curr_position.x(), curr_position.y(), 0);
2336 cov_ellipsis_obj->setCovMatrix(mat, 2);
2338 this->m_win->unlockAccess3DScene();
2339 this->m_win->forceRepaint();
2344 template <
class GRAPH_T>
2352 "Cannot toggle visibility of specified object.\n " 2353 "Make sure that the corresponding visualization flag ( %s " 2354 ") is set to true in the .ini file.\n",
2356 std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));
2361 template <
class GRAPH_T>
2365 parent_t::loadParams(source_fname);
2367 m_partitioner.options.loadFromConfigFileName(
2368 source_fname,
"EdgeRegistrationDeciderParameters");
2369 m_laser_params.loadFromConfigFileName(
2370 source_fname,
"EdgeRegistrationDeciderParameters");
2371 m_lc_params.loadFromConfigFileName(
2372 source_fname,
"EdgeRegistrationDeciderParameters");
2376 m_consec_icp_constraint_factor =
source.read_double(
2377 "EdgeRegistrationDeciderParameters",
"consec_icp_constraint_factor",
2379 m_lc_icp_constraint_factor =
source.read_double(
2380 "EdgeRegistrationDeciderParameters",
"lc_icp_constraint_factor", 0.70,
2384 int min_verbosity_level =
source.read_int(
2385 "EdgeRegistrationDeciderParameters",
"class_verbosity", 1,
false);
2390 template <
class GRAPH_T>
2394 using namespace std;
2396 cout <<
"------------------[Pair-wise Consistency of ICP Edges - " 2397 "Registration Procedure Summary]------------------" 2400 parent_t::printParams();
2401 m_partitioner.options.dumpToConsole();
2402 m_laser_params.dumpToConsole();
2403 m_lc_params.dumpToConsole();
2405 cout <<
"Scan-matching ICP Constraint factor: " 2406 << m_consec_icp_constraint_factor << endl;
2407 cout <<
"Loop-closure ICP Constraint factor: " 2408 << m_lc_icp_constraint_factor << endl;
2414 template <
class GRAPH_T>
2421 std::stringstream class_props_ss;
2422 class_props_ss <<
"Pair-wise Consistency of ICP Edges - Registration " 2423 "Procedure Summary: " 2425 class_props_ss << this->header_sep << std::endl;
2428 const std::string time_res = this->m_time_logger.getStatsAsText();
2429 const std::string output_res = this->getLogAsString();
2432 report_str->clear();
2433 parent_t::getDescriptiveReport(report_str);
2435 *report_str += class_props_ss.str();
2436 *report_str += this->report_sep;
2438 *report_str += time_res;
2439 *report_str += this->report_sep;
2441 *report_str += output_res;
2442 *report_str += this->report_sep;
2447 template <
class GRAPH_T>
2451 partitions_out = this->getCurrentPartitions();
2454 template <
class GRAPH_T>
2455 const std::vector<std::vector<uint32_t>>&
2458 return m_curr_partitions;
2461 template <
class GRAPH_T>
2463 bool full_update ,
bool is_first_time_node_reg )
2467 using namespace std;
2468 this->m_time_logger.enter(
"updateMapPartitions");
2475 "updateMapPartitions: Full partitioning of map was issued");
2478 m_partitioner.clear();
2479 nodes_to_scans = this->m_nodes_to_laser_scans2D;
2484 if (is_first_time_node_reg)
2486 nodes_to_scans.insert(
2488 this->m_graph->root,
2489 this->m_nodes_to_laser_scans2D.at(this->m_graph->root)));
2493 nodes_to_scans.insert(
2495 this->m_graph->nodeCount() - 1,
2496 this->m_nodes_to_laser_scans2D.at(
2497 this->m_graph->nodeCount() - 1)));
2503 for (
auto it = nodes_to_scans.begin(); it != nodes_to_scans.end(); ++it)
2508 "nodeID \"" << it->first <<
"\" has invalid laserScan");
2514 const auto& search = this->m_graph->nodes.find(it->first);
2515 if (search == this->m_graph->nodes.end())
2522 const auto curr_constraint =
constraint_t(search->second);
2529 m_partitioner.addMapFrame(sf, *pose3d);
2533 size_t curr_size = m_curr_partitions.size();
2534 m_last_partitions.resize(curr_size);
2535 for (
size_t i = 0; i < curr_size; i++)
2537 m_last_partitions[i] = m_curr_partitions[i];
2540 m_partitioner.updatePartitions(m_curr_partitions);
2543 this->m_time_logger.leave(
"updateMapPartitions");
2550 template <
class GRAPH_T>
2552 : laser_scans_color(0, 20, 255),
2553 keystroke_laser_scans(
"l"),
2554 has_read_config(false)
2561 template <
class GRAPH_T>
2566 template <
class GRAPH_T>
2568 std::ostream& out)
const 2572 out <<
"Use scan-matching constraints = " 2573 << (use_scan_matching ?
"TRUE" :
"FALSE") << std::endl;
2574 out <<
"Num. of previous nodes to check ICP against = " 2575 << prev_nodes_for_ICP << std::endl;
2576 out <<
"Visualize laser scans = " 2577 << (visualize_laser_scans ?
"TRUE" :
"FALSE") << std::endl;
2581 template <
class GRAPH_T>
2588 source.read_bool(section,
"use_scan_matching",
true,
false);
2589 prev_nodes_for_ICP =
source.read_int(
2591 "prev_nodes_for_ICP",
2593 visualize_laser_scans =
source.read_bool(
2594 "VisualizationParameters",
"visualize_laser_scans",
true,
false);
2596 has_read_config =
true;
2602 template <
class GRAPH_T>
2604 : keystroke_map_partitions(
"b"),
2605 balloon_elevation(3),
2606 balloon_radius(0.5),
2607 balloon_std_color(153, 0, 153),
2608 balloon_curr_color(62, 0, 80),
2609 connecting_lines_color(balloon_std_color),
2610 has_read_config(false)
2614 template <
class GRAPH_T>
2619 template <
class GRAPH_T>
2621 std::ostream& out)
const 2624 using namespace std;
2627 ss <<
"Min. node difference for loop closure = " 2628 << LC_min_nodeid_diff << endl;
2629 ss <<
"Remote NodeIDs to consider the potential loop closure = " 2630 << LC_min_remote_nodes << endl;
2631 ss <<
"Min EigenValues ratio for accepting a hypotheses set = " 2632 << LC_eigenvalues_ratio_thresh << endl;
2633 ss <<
"Check only current node's partition for loop closures = " 2634 << (LC_check_curr_partition_only ?
"TRUE" :
"FALSE") << endl;
2635 ss <<
"New registered nodes required for full partitioning = " 2636 << full_partition_per_nodes << endl;
2637 ss <<
"Visualize map partitions = " 2638 << (visualize_map_partitions ?
"TRUE" :
"FALSE") << endl;
2644 template <
class GRAPH_T>
2649 LC_min_nodeid_diff =
source.read_int(
2650 "GeneralConfiguration",
"LC_min_nodeid_diff", 30,
false);
2651 LC_min_remote_nodes =
2652 source.read_int(section,
"LC_min_remote_nodes", 3,
false);
2653 LC_eigenvalues_ratio_thresh =
2654 source.read_double(section,
"LC_eigenvalues_ratio_thresh", 2,
false);
2655 LC_check_curr_partition_only =
2656 source.read_bool(section,
"LC_check_curr_partition_only",
true,
false);
2657 full_partition_per_nodes =
2658 source.read_int(section,
"full_partition_per_nodes", 50,
false);
2659 visualize_map_partitions =
source.read_bool(
2660 "VisualizationParameters",
"visualize_map_partitions",
true,
false);
2662 has_read_config =
true;
mrpt::obs::CObservation2DRangeScan::Ptr scan
void toggleMapPartitionsVisualization()
Toggle the map partitions visualization objects.
const partitions_t & getCurrentPartitions() const
GRAPH_T::global_pose_t pose
double generatePWConsistencyElement(const mrpt::graphs::TNodeID &a1, const mrpt::graphs::TNodeID &a2, const mrpt::graphs::TNodeID &b1, const mrpt::graphs::TNodeID &b2, const hypotsp_t &hypots, const paths_t *opt_paths=NULL)
Return the pair-wise consistency between the observations of the given nodes.
void insert(const CObservation::Ptr &obs)
Inserts a new observation to the list: The pointer to the objects is copied, thus DO NOT delete the p...
Holds the data of an information path.
std::vector< path_t > paths_t
void loadParams(const std::string &source_fname)
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
VerbosityLevel
Enumeration of available verbosity levels.
const_iterator find(const KEY &key) const
A set of object, which are referenced to the coordinates framework established in this object...
#define THROW_EXCEPTION(msg)
void initMapPartitionsVisualization()
Initialize the visualization of the map partition objects.
typename GRAPH_T::constraint_t::type_value pose_t
type of underlying poses (2D/3D).
typename GRAPH_T::global_pose_t global_pose_t
void dumpToTextStream(std::ostream &out) const
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
This method load the options from a ".ini"-like file or memory-stored string list.
void resizeWindow(size_t new_size)
Resize the window.
void updateCurrCovarianceVisualization()
double DEG2RAD(const double x)
Degrees to radians.
void getMinUncertaintyPath(const mrpt::graphs::TNodeID from, const mrpt::graphs::TNodeID to, path_t *path) const
Given two nodeIDs compute and return the path connecting them.
virtual bool updateState(mrpt::obs::CActionCollection::Ptr action, mrpt::obs::CSensoryFrame::Ptr observations, mrpt::obs::CObservation::Ptr observation)
This class allows loading and storing values and vectors of different types from ".ini" files easily.
void execDijkstraProjection(mrpt::graphs::TNodeID starting_node=0, mrpt::graphs::TNodeID ending_node=INVALID_NODEID)
compute the minimum uncertainty of each node position with regards to the graph root.
static CPose3DPDF * createFrom2D(const CPosePDF &o)
This is a static transformation method from 2D poses to 3D PDFs, preserving the representation type (...
void getDescriptiveReport(std::string *report_str) const
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
void splitPartitionToGroups(std::vector< uint32_t > &partition, std::vector< uint32_t > *groupA, std::vector< uint32_t > *groupB, int max_nodes_in_group=5)
Split an existing partition to Groups.
pose_t init_estim
Initial ICP estimation.
TSlidingWindow mahal_distance_ICP_odom_win
Keep track of the mahalanobis distance between the initial pose difference and the suggested new edge...
static hypot_t * findHypotByID(const hypotsp_t &vec_hypots, const size_t &id, bool throw_exc=true)
Given a vector of THypothesis objects, find the one that has the given ID.
void loadFromConfigFile(const mrpt::config::CConfigFileBase &source, const std::string §ion)
This method load the options from a ".ini"-like file or memory-stored string list.
virtual ~CLoopCloserERD()
GLsizei GLsizei GLuint * obj
void computeCentroidOfNodesVector(const std::vector< uint32_t > &nodes_list, std::pair< double, double > *centroid_coords) const
Compute the Centroid of a group of a vector of node positions.
node_props_t from_params
Ad.
Struct for passing additional parameters to the getICPEdge call.
#define MRPT_LOG_WARN_STREAM(__CONTENTS)
void registerHypothesis(const hypot_t &h)
Wrapper around the registerNewEdge method which accepts a THypothesis object instead.
const mrpt::graphs::TNodeID & getDestination() const
Return the Destination node of this path.
void getAsString(std::string *str) const
GLubyte GLubyte GLubyte GLubyte w
void evaluatePartitionsForLC(const partitions_t &partitions)
Evaluate the given partitions for loop closures.
std::vector< hypot_t * > hypotsp_t
static const path_t * findPathByEnds(const paths_t &vec_paths, const mrpt::graphs::TNodeID &src, const mrpt::graphs::TNodeID &dst, bool throw_exc=true)
Given a vector of TUncertaintyPath objects, find the one that has the given source and destination no...
float goodness
A goodness measure for the alignment, it is a [0,1] range indicator of percentage of correspondences...
SLAM methods related to graphs of pose constraints.
This class allows loading and storing values and vectors of different types from a configuration text...
This base provides a set of functions for maths stuff.
3D segment, consisting of two points.
bool mahalanobisDistanceOdometryToICPEdge(const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to, const constraint_t &rel_edge)
brief Compare the suggested ICP edge against the initial node difference.
#define MRPT_LOG_DEBUG_FMT(_FMT_STRING,...)
Use: MRPT_LOG_DEBUG_FMT("i=%u", i);
constraint_t curr_pose_pdf
Current path position + corresponding covariance.
typename GRAPH_T::constraint_t constraint_t
Handy typedefs.
Eigen::Matrix< dataType, 4, 4 > inverse(Eigen::Matrix< dataType, 4, 4 > &pose)
This namespace contains representation of robot actions and observations.
Declares a class for storing a "sensory frame", a set of "observations" taken by the robot approximat...
This object renders a 2D laser scan by means of three elements: the points, the line along end-points...
std::map< std::string, int > m_edge_types_to_nums
Keep track of the registered edge types.
#define MRPT_LOG_DEBUG_STREAM(__CONTENTS)
Use: MRPT_LOG_DEBUG_STREAM("Var=" << value << " foo=" << foo_var);
GLsizei const GLchar ** string
bool fillNodePropsFromGroupParams(const mrpt::graphs::TNodeID &nodeID, const std::map< mrpt::graphs::TNodeID, node_props_t > &group_params, node_props_t *node_props)
Fill the TNodeProps instance using the parameters from the map.
std::vector< std::vector< uint32_t > > partitions_t
Typedef for referring to a list of partitions.
bool computeDominantEigenVector(const mrpt::math::CMatrixDouble &consist_matrix, mrpt::math::dynamic_vector< double > *eigvec, bool use_power_method=false)
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
MAT::Scalar mahalanobisDistance2(const VECTORLIKE1 &X, const VECTORLIKE2 &MU, const MAT &COV)
Computes the squared mahalanobis distance of a vector X given the mean MU and the covariance inverse ...
void setWindowManagerPtr(mrpt::graphslam::CWindowManager *win_manager)
void addToPath(const mrpt::graphs::TNodeID &node, const constraint_t &edge)
add a new link in the current path.
void evalPWConsistenciesMatrix(const mrpt::math::CMatrixDouble &consist_matrix, const hypotsp_t &hypots_pool, hypotsp_t *valid_hypots)
Evalute the consistencies matrix, fill the valid hypotheses.
#define ASSERTDEBMSG_(f, __ERROR_MSG)
typename parent_t::nodes_to_scans2D_t nodes_to_scans2D_t
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void addToPaths(std::set< path_t *> *pool_of_paths, const path_t &curr_path, const std::set< mrpt::graphs::TNodeID > &neibors) const
Append the paths starting from the current node.
static hypot_t * findHypotByEnds(const hypotsp_t &vec_hypots, const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to, bool throw_exc=true)
Given a vector of THypothesis objects, find the one that has the given start and end nodes...
std::map< mrpt::graphs::TNodeID, node_props_t > group_t
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
virtual bool getICPEdge(const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to, constraint_t *rel_edge, mrpt::slam::CICP::TReturnInfo *icp_info=NULL, const TGetICPEdgeAdParams *ad_params=NULL)
Get the ICP Edge between the provided nodes.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
node_props_t to_params
Ad.
void updateLaserScansVisualization()
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
A solid or wire-frame sphere.
void checkPartitionsForLC(partitions_t *partitions_for_LC)
Check the registered so far partitions for potential loop closures.
CMatrixFixedNumeric< double, 3, 3 > CMatrixDouble33
A RGB color - floats in the range [0,1].
void dumpToTextStream(std::ostream &out) const
This method should clearly display all the contents of the structure in textual form, sending it to a std::ostream.
void registerNewEdge(const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to, const constraint_t &rel_edge)
Struct for passing additional parameters to the generateHypotsPool call.
The ICP algorithm return information.
virtual void fetchNodeIDsForScanMatching(const mrpt::graphs::TNodeID &curr_nodeID, std::set< mrpt::graphs::TNodeID > *nodes_set)
Fetch a list of nodes with regards prior to the given nodeID for which to try and add scan matching e...
The namespace for 3D scene representation and rendering.
GLsizei GLsizei GLchar * source
void toggleLaserScansVisualization()
togle the LaserScans visualization on and off
void updateMapPartitions(bool full_update=false, bool is_first_time_node_reg=false)
Split the currently registered graph nodes into partitions.
uint64_t TNodeID
A generic numeric type for unique IDs of nodes or entities.
Edge Registration Decider scheme specialized in Loop Closing.
Classes for creating GUI windows for 2D and 3D visualization.
T absDiff(const T &lhs, const T &rhs)
Absolute difference between two numbers.
mrpt::graphslam::TUncertaintyPath< GRAPH_T > * popMinUncertaintyPath(std::set< path_t *> *pool_of_paths) const
Find the minimum uncertainty path from te given pool of TUncertaintyPath instances.
GLsizei const GLfloat * value
void initCurrCovarianceVisualization()
void updateMapPartitionsVisualization()
Update the map partitions visualization.
void initLaserScansVisualization()
A 2D ellipse or 3D ellipsoid, depending on the size of the m_cov matrix (2x2 or 3x3).
typename GRAPH_T::edges_map_t::const_iterator edges_citerator
void notifyOfWindowEvents(const std::map< std::string, bool > &events_occurred)
std::vector< mrpt::graphs::TNodeID > nodes_traversed
Nodes that the Path comprises of.
An edge hypothesis between two nodeIDs.
void assertIsBetweenNodeIDs(const mrpt::graphs::TNodeID &from, const mrpt::graphs::TNodeID &to) const
Assert that the current path is between the given nodeIDs.
A set of independent lines (or segments), one line with its own start and end positions (X...
void dumpVisibilityErrorMsg(std::string viz_flag, int sleep_time=500)
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
#define MRPT_LOG_ERROR_STREAM(__CONTENTS)
void generateHypotsPool(const std::vector< uint32_t > &groupA, const std::vector< uint32_t > &groupB, hypotsp_t *generated_hypots, const TGenerateHypotsPoolAdParams *ad_params=NULL)
Generate the hypothesis pool for all the inter-group constraints between two groups of nodes...
GLenum const GLfloat * params
void getEdgesStats(std::map< std::string, int > *edge_types_to_num) const
const Scalar * const_iterator
Internal auxiliary classes.
std::string getSTLContainerAsString(const T &t)
Return a STL container in std::string form.
typename mrpt::graphs::detail::THypothesis< GRAPH_T > hypot_t
Class acts as a container for storing pointers to mrpt::gui::CDisplayWindow3D, mrpt::graphslam::CWind...
bool approximatelyEqual(T1 a, T1 b, T2 epsilon)
Compare 2 floats and determine whether they are equal.
virtual void addScanMatchingEdges(const mrpt::graphs::TNodeID &curr_nodeID)
Addd ICP constraints from X previous nodeIDs up to the given nodeID.
bool getPropsOfNodeID(const mrpt::graphs::TNodeID &nodeID, global_pose_t *pose, mrpt::obs::CObservation2DRangeScan::Ptr &scan, const node_props_t *node_props=NULL) const
Fill the pose and LaserScan for the given nodeID.
void generatePWConsistenciesMatrix(const std::vector< uint32_t > &groupA, const std::vector< uint32_t > &groupB, const hypotsp_t &hypots_pool, mrpt::math::CMatrixDouble *consist_matrix, const paths_t *groupA_opt_paths=NULL, const paths_t *groupB_opt_paths=NULL)
Compute the pair-wise consistencies Matrix.
#define MRPT_LOG_INFO(_STRING)
#define MRPT_UNUSED_PARAM(a)
Determines whether this is an X86 or AMD64 platform.
TSlidingWindow goodness_threshold_win
Keep track of ICP Goodness values for ICP between nearby nodes and adapt the Goodness threshold based...