9 #ifndef CONSTRAINED_POSE_NETWORK_H
10 #define CONSTRAINED_POSE_NETWORK_H
38 #include <type_traits>
49 template <
class GRAPH_T>
struct graph_ops;
54 class MAPS_IMPLEMENTATION,
55 class NODE_ANNOTATIONS,
56 class EDGE_ANNOTATIONS
62 class MAPS_IMPLEMENTATION,
63 class NODE_ANNOTATIONS,
64 class EDGE_ANNOTATIONS
139 NODE_ANNOTATIONS(other)
145 static_cast<const NODE_ANNOTATIONS
>(*
this) ==
static_cast<const NODE_ANNOTATIONS
>(other));
148 return ( !(*
this == other) );
152 o << global_pose.asString() <<
"| " << global_pose.retAnnotsAsString();
162 typedef typename MAPS_IMPLEMENTATION::template map<mrpt::utils::TNodeID,global_pose_t>
global_poses_t;
232 const std::string& fileName,
bool collapse_dup_edges =
true)
260 mrpt::opengl::CSetOfObjectsPtr
object,
266 bool is_multirobot=
false;
268 std::unique_ptr<visualizer_t> viz;
271 std::auto_ptr<visualizer_t> viz;
277 viz.reset(
new visualizer_multirobot_t(*
this));
280 viz.reset(
new visualizer_t(*
this));
282 viz->getAs3DObject(
object, viz_params);
345 const bool& auto_expand_set=
true)
const {
347 using namespace mrpt;
355 "\nInvalid pointer to a CNetworkOfPoses instance is given. Exiting..\n");
359 TNodeID root_node = root_node_in;
361 ASSERTMSG_(node_IDs.find(root_node) != node_IDs.end(),
362 "\nRoot_node does not exist in the given node_IDs set. Exiting.\n");
368 "Very few nodes [%lu] for which to extract a subgraph. Exiting\n",
369 static_cast<unsigned long>(node_IDs.size())));
374 bool is_fully_connected_graph =
true;
375 std::set<TNodeID> node_IDs_real;
376 if (*node_IDs.rbegin() - *node_IDs.begin() + 1 == node_IDs.size()) {
377 node_IDs_real = node_IDs;
380 is_fully_connected_graph =
false;
382 if (auto_expand_set) {
383 for (
TNodeID curr_node_ID = *node_IDs.begin();
384 curr_node_ID != *node_IDs.rbegin(); ++curr_node_ID) {
385 node_IDs_real.insert(curr_node_ID);
389 node_IDs_real = node_IDs;
395 node_IDs_it = node_IDs_real.begin();
396 node_IDs_it != node_IDs_real.end();
401 for (own_it =
nodes.begin(); own_it !=
nodes.end(); ++own_it) {
402 if (*node_IDs_it == own_it->first) {
407 format(
"NodeID [%lu] can't be found in the initial graph.",
408 static_cast<unsigned long>(*node_IDs_it)));
411 sub_graph->
nodes.insert(make_pair(*node_IDs_it, curr_node));
422 root_node = sub_graph->
nodes.begin()->first;
424 sub_graph->
root = root_node;
437 const TNodeID& from = it->first.first;
438 const TNodeID& to = it->first.second;
442 if (sub_graph->
nodes.find(from) != sub_graph->
nodes.end() &&
443 sub_graph->
nodes.find(to) != sub_graph->
nodes.end()) {
448 if (!auto_expand_set && !is_fully_connected_graph) {
453 std::set<TNodeID> root_neighbors;
456 if (root_neighbors.empty()) {
461 if ((*root_it == *sub_graph->
nodes.rbegin())) {
478 bool dijkstra_runs_successfully =
false;
482 while (!dijkstra_runs_successfully) {
484 dijkstra_t dijkstra(*sub_graph, sub_graph->
root);
485 dijkstra_runs_successfully =
true;
488 dijkstra_runs_successfully =
false;
490 set<TNodeID> unconnected_nodeIDs;
500 const TNodeID& island_highest = *unconnected_nodeIDs.rbegin();
501 const TNodeID& island_lowest = *unconnected_nodeIDs.begin();
508 std::set<TNodeID> mainland;
511 n_it = sub_graph->
nodes.begin();
512 n_it != sub_graph->
nodes.end();
514 bool is_there =
false;
518 uncon_it = unconnected_nodeIDs.begin();
519 uncon_it != unconnected_nodeIDs.end();
522 if (n_it->first == *uncon_it) {
529 mainland.insert(n_it->first);
533 bool is_single_island = (island_highest - island_lowest + 1 ==
534 unconnected_nodeIDs.size());
536 if (is_single_island) {
544 const std::set<TNodeID>& island = unconnected_nodeIDs;
553 std::vector<std::set<TNodeID> > vec_of_islands;
554 std::set<TNodeID> curr_island;
555 TNodeID prev_nodeID = *unconnected_nodeIDs.begin();
556 curr_island.insert(prev_nodeID);
558 it = ++unconnected_nodeIDs.begin();
559 *it < sub_graph->
root && it != unconnected_nodeIDs.end();
561 if (!(
absDiff(*it, prev_nodeID) == 1)) {
562 vec_of_islands.push_back(curr_island);
565 curr_island.insert(*it);
570 vec_of_islands.push_back(curr_island);
603 const bool hypots_from_other_to_self=
true,
604 std::map<TNodeID, TNodeID>* old_to_new_nodeID_mappings_out=NULL) {
614 const self_t& graph_from = (hypots_from_other_to_self? other : *
this);
615 const self_t& graph_to = (hypots_from_other_to_self? *this : other);
623 for (hypots_cit_t h_cit = common_hypots.begin();
624 h_cit != common_hypots.end();
628 format(
"NodeID %lu is not found in (from) graph", h_cit->from))
630 format(
"NodeID %lu is not found in (to) graph", h_cit->to))
635 for (nodes_cit_t n_cit = this->nodes.begin();
636 n_cit != this->nodes.end();
638 if (n_cit->first > max_nodeID) {
639 max_nodeID = n_cit->first;
642 TNodeID renum_start = max_nodeID + 1;
643 size_t renum_counter = 0;
648 std::map<TNodeID, TNodeID>* old_to_new_nodeID_mappings;
654 std::map<TNodeID, TNodeID> mappings_tmp;
657 if (old_to_new_nodeID_mappings_out) {
658 old_to_new_nodeID_mappings = old_to_new_nodeID_mappings_out;
661 old_to_new_nodeID_mappings = &mappings_tmp;
663 old_to_new_nodeID_mappings->clear();
668 for (nodes_cit_t n_cit = other.
nodes.begin();
669 n_cit != other.
nodes.end();
671 TNodeID new_nodeID = renum_start + renum_counter++;
672 old_to_new_nodeID_mappings->insert(make_pair(
675 this->nodes.insert(make_pair(
676 new_nodeID, n_cit->second));
684 for (hypots_cit_t h_cit = common_hypots.begin();
685 h_cit != common_hypots.end();
688 if (hypots_from_other_to_self) {
689 from = old_to_new_nodeID_mappings->at(h_cit->from);
694 to = old_to_new_nodeID_mappings->at(h_cit->to);
704 g_cit = other.
begin();
705 g_cit != other.
end();
707 TNodeID new_from = old_to_new_nodeID_mappings->at(g_cit->first.first);
708 TNodeID new_to = old_to_new_nodeID_mappings->at(g_cit->first.second);
709 this->
insertEdge(new_from, new_to, g_cit->second);
731 const std::set<TNodeID>& groupA,
732 const std::set<TNodeID>& groupB) {
736 "\nInvalid pointer to a CNetworkOfPoses instance is given. Exiting..\n");
737 ASSERTMSG_(!groupA.empty(),
"\ngroupA is empty.");
738 ASSERTMSG_(!groupB.empty(),
"\ngroupB is empty.");
742 *groupA.rend() < *groupB.rbegin() ||
743 *groupA.rbegin() > *groupB.rend(),
744 "Groups A, B contain overlapping nodeIDs");
748 const std::set<TNodeID>& low_nodeIDs =
749 *groupA.rbegin() < *groupB.rbegin() ? groupA : groupB;
750 const std::set<TNodeID>& high_nodeIDs =
751 *groupA.rbegin() > *groupB.rbegin() ? groupA : groupB;
754 const TNodeID& from_nodeID = *low_nodeIDs.rbegin();
755 const TNodeID& to_nodeID = *high_nodeIDs.begin();
769 bool ignoreCovariances =
true)
const {
788 ASSERTMSG_(itEdge!=
BASE::edges.
end(),
format(
"Request for edge %u->%u that doesn't exist in graph.",
static_cast<unsigned int>(from_id),
static_cast<unsigned int>(to_id)));
831 ASSERTMSG_(graph,
"Invalid pointer to the graph instance was provided.");
843 template <
class CPOSE,
class MAPS_IMPLEMENTATION,
class NODE_ANNOTATIONS,
class EDGE_ANNOTATIONS>
852 template <
class CPOSE,
class MAPS_IMPLEMENTATION,
class NODE_ANNOTATIONS,
class EDGE_ANNOTATIONS>
888 class MAPS_IMPLEMENTATION,
889 class NODE_ANNOTATIONS,
890 class EDGE_ANNOTATIONS
896 return std::string(
"mrpt::graphs::CNetworkOfPoses<")
#define MRPT_DECLARE_TTYPENAME(_TYPE)
The Dijkstra algorithm for finding the shortest path between a given source node in a (weighted) dire...
A directed graph with the argument of the template specifying the type of the annotations in the edge...
void getNeighborsOf(const TNodeID nodeID, std::set< TNodeID > &neighborIDs) const
Return the list of all neighbors of "nodeID", by creating a list of their node IDs.
edges_map_t edges
The public member with the directed edges in the graph.
edges_map_t::const_iterator const_iterator
void insertEdge(TNodeID from_nodeID, TNodeID to_nodeID, const edge_t &edge_value)
Insert an edge (from -> to) with the given edge value.
void clearEdges()
Erase all edges.
A directed graph of pose constraints, with edges being the relative poses between pairs of nodes iden...
MAPS_IMPLEMENTATION::template map< mrpt::utils::TNodeID, CPOSE > global_poses_pdf_t
A map from pose IDs to their global coordinate estimates, with uncertainty.
void readAsText(std::istream &i)
Reads as text in the format used by TORO, HoG-man, G2O.
CNetworkOfPoses< CPOSE, MAPS_IMPLEMENTATION, NODE_ANNOTATIONS, EDGE_ANNOTATIONS > self_t
My own type.
static void connectGraphPartitions(self_t *sub_graph, const std::set< TNodeID > &groupA, const std::set< TNodeID > &groupB)
Add an edge between the last node of the group with the lower nodeIDs and the first node of the highe...
void clear()
Empty all edges, nodes and set root to ID 0.
MAPS_IMPLEMENTATION maps_implementation_t
The type of map's implementation (=MAPS_IMPLEMENTATION template argument)
double getEdgeSquareError(const mrpt::utils::TNodeID from_id, const mrpt::utils::TNodeID to_id, bool ignoreCovariances=true) const
Computes the square error of one pose constraints (edge) with respect to the global poses in nodes If...
MAPS_IMPLEMENTATION::template map< mrpt::utils::TNodeID, global_pose_t > global_poses_t
A map from pose IDs to their global coordinate estimates, without uncertainty (the "most-likely value...
global_poses_t nodes
The nodes (vertices) of the graph, with their estimated "global" (with respect to root) position,...
size_t collapseDuplicatedEdges()
Look for duplicated edges (even in opposite directions) between all pairs of nodes and fuse them.
EDGE_ANNOTATIONS edge_annotations_t
The extra annotations in edges, apart from a constraint_t.
static void addVirtualEdge(self_t *graph, const TNodeID &from, const TNodeID &to)
Add a virtual edge between two nodes in the given graph.
void dijkstra_nodes_estimate()
Spanning tree computation of a simple estimation of the global coordinates of each node just from the...
mrpt::utils::TNodeID root
The ID of the node that is the origin of coordinates, used as reference by all coordinates in nodes.
void extractSubGraph(const std::set< TNodeID > &node_IDs, self_t *sub_graph, const TNodeID root_node_in=INVALID_NODEID, const bool &auto_expand_set=true) const
Find the edges between the nodes in the node_IDs set and fill given graph pointer accordingly.
CPOSE::type_value constraint_no_pdf_t
The type of edges or their means if they are PDFs (that is, a simple "edge" value)
CPOSE constraint_t
The type of PDF poses in the contraints (edges) (=CPOSE template argument)
void mergeGraph(const self_t &other, const typename std::vector< detail::THypothesis< self_t > > &common_hypots, const bool hypots_from_other_to_self=true, std::map< TNodeID, TNodeID > *old_to_new_nodeID_mappings_out=NULL)
Integrate given graph into own graph using the list of provided common THypotheses.
double chi2() const
Returns the total chi-squared error of the graph.
void saveToTextFile(const std::string &fileName) const
Saves to a text file in the format used by TORO, HoG-man, G2O.
NODE_ANNOTATIONS node_annotations_t
The extra annotations in nodes, apart from a constraint_no_pdf_t.
void loadFromTextFile(const std::string &fileName, bool collapse_dup_edges=true)
Loads from a text file in the format used by TORO & HoG-man (more on the format here) Recognized line...
bool edges_store_inverse_poses
False (default) if an edge i->j stores the normal relative pose of j as seen from i: True if an edge...
void getAs3DObject(mrpt::opengl::CSetOfObjectsPtr object, const mrpt::utils::TParametersDouble &viz_params) const
Return 3D Visual Representation of the edges and nodes in the network of poses.
mrpt::graphs::CDirectedGraph< CPOSE, EDGE_ANNOTATIONS > BASE
The base class "CDirectedGraph<CPOSE,EDGE_ANNOTATIONS>" */.
size_t nodeCount() const
Return number of nodes in the list nodes of global coordinates (may be different that all nodes appea...
double getGlobalSquareError(bool ignoreCovariances=true) const
Computes the overall square error from all the pose constraints (edges) with respect to the global po...
double getEdgeSquareError(const typename BASE::edges_map_t::const_iterator &itEdge, bool ignoreCovariances=true) const
Computes the square error of one pose constraints (edge) with respect to the global poses in nodes If...
void writeAsText(std::ostream &o) const
Writes as text in the format used by TORO, HoG-man, G2O.
CNetworkOfPoses()
Default constructor (just sets root to "0" and edges_store_inverse_poses to "false")
Wrapper class that provides visualization of a network of poses that have been registered by many gra...
Base class for C*Visualizer classes.
Custom exception class that passes information in case an unconnected graph is passed to a Dijkstra i...
void getUnconnectedNodeIDs(std::set< mrpt::utils::TNodeID > *set_nodeIDs) const
Fill set with the nodeIDs Dijkstra algorithm could not reach starting from the root node.
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
const Scalar * const_iterator
GLsizei GLsizei GLuint * obj
GLenum GLsizei GLenum format
GLsizei const GLfloat * value
GLsizei const GLchar ** string
uint64_t TNodeID
The type for node IDs in graphs of different types.
#define ASSERTMSG_(f, __ERROR_MSG)
Internal functions for MRPT.
Abstract graph and tree data structures, plus generic graph algorithms.
CNetworkOfPoses< mrpt::poses::CPose2D, mrpt::utils::map_traits_stdmap > CNetworkOfPoses2D
The specialization of CNetworkOfPoses for poses of type CPose2D (not a PDF!), also implementing seria...
mrpt::utils::CStream & operator<<(mrpt::utils::CStream &out, const CNetworkOfPoses< CPOSE, MAPS_IMPLEMENTATION, NODE_ANNOTATIONS, EDGE_ANNOTATIONS > &obj)
Binary serialization (write) operator "stream << graph".
CNetworkOfPoses< mrpt::poses::CPose3D, mrpt::utils::map_traits_stdmap > CNetworkOfPoses3D
The specialization of CNetworkOfPoses for poses of type mrpt::poses::CPose3D (not a PDF!...
CNetworkOfPoses< mrpt::poses::CPosePDFGaussianInf, mrpt::utils::map_traits_stdmap, mrpt::graphs::detail::TMRSlamNodeAnnotations > CNetworkOfPoses2DInf_NA
Specializations of CNetworkOfPoses for graphs whose nodes inherit from TMRSlamNodeAnnotations struct.
CNetworkOfPoses< mrpt::poses::CPose3DPDFGaussianInf, mrpt::utils::map_traits_stdmap, mrpt::graphs::detail::TMRSlamNodeAnnotations > CNetworkOfPoses3DInf_NA
CNetworkOfPoses< mrpt::poses::CPosePDFGaussian, mrpt::utils::map_traits_stdmap > CNetworkOfPoses2DCov
The specialization of CNetworkOfPoses for poses of type CPosePDFGaussian, also implementing serializa...
CNetworkOfPoses< mrpt::poses::CPosePDFGaussianInf, mrpt::utils::map_traits_stdmap > CNetworkOfPoses2DInf
The specialization of CNetworkOfPoses for poses of type CPosePDFGaussianInf, also implementing serial...
CNetworkOfPoses< mrpt::poses::CPose3DPDFGaussianInf, mrpt::utils::map_traits_stdmap > CNetworkOfPoses3DInf
The specialization of CNetworkOfPoses for poses of type CPose3DPDFGaussianInf, also implementing seri...
CNetworkOfPoses< mrpt::poses::CPose3DPDFGaussian, mrpt::utils::map_traits_stdmap > CNetworkOfPoses3DCov
The specialization of CNetworkOfPoses for poses of type CPose3DPDFGaussian, also implementing seriali...
mrpt::utils::CStream & operator>>(mrpt::utils::CStream &in, CNetworkOfPoses< CPOSE, MAPS_IMPLEMENTATION, NODE_ANNOTATIONS, EDGE_ANNOTATIONS > &obj)
Binary serialization (read) operator "stream >> graph".
This base provides a set of functions for maths stuff.
T absDiff(const T &lhs, const T &rhs)
Absolute difference between two numbers.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
The type of each global pose in nodes: an extension of the TYPE_EDGES pose with any optional user-def...
The type of each global pose in nodes: an extension of the constraint_no_pdf_t pose with any optional...
global_pose_t(const global_pose_t &other)
Copy constructor - delegate copying to the NODE_ANNOTATIONS struct.
bool operator==(const global_pose_t &other) const
bool operator!=(const global_pose_t &other) const
global_pose_t(const ARG1 &a1, const ARG2 &a2)
friend std::ostream & operator<<(std::ostream &o, const self_t &global_pose)
global_pose_t(const ARG1 &a1)
CNetworkOfPoses< CPOSE, MAPS_IMPLEMENTATION, NODE_ANNOTATIONS, EDGE_ANNOTATIONS >::global_pose_t self_t
global_pose_t()
Potential class constructors.
An edge hypothesis between two nodeIDs.
Struct to be used as the NODE_ANNOTATIONS template argument in CNetworkOfPoses class instances for us...
Struct to be used as the NODE_ANNOTATIONS template argument in CNetworkOfPoses class instances for us...
a helper struct with static template functions
static void graph_of_poses_dijkstra_init(graph_t *g)
static void read_graph_of_poses_from_binary_file(graph_t *g, mrpt::utils::CStream &in)
static void load_graph_of_poses_from_text_stream(graph_t *g, std::istream &f, const std::string &fil=std::string("(none)"))
static size_t graph_of_poses_collapse_dup_edges(graph_t *g)
static void save_graph_of_poses_to_ostream(const graph_t *g, std::ostream &f)
static void load_graph_of_poses_from_text_file(graph_t *g, const std::string &fil)
static void save_graph_of_poses_to_binary_file(const graph_t *g, mrpt::utils::CStream &out)
static double graph_edge_sqerror(const graph_t *g, const typename mrpt::graphs::CDirectedGraph< typename graph_t::constraint_t >::edges_map_t::const_iterator &itEdge, bool ignoreCovariances)
static void save_graph_of_poses_to_text_file(const graph_t *g, const std::string &fil)
A template to obtain the type of its argument as a string at compile time.
Traits for using a mrpt::utils::map_as_vector<> (dense, fastest representation)
Traits for using a std::map<> (sparse representation)