Main MRPT website > C++ reference
MRPT logo
spantree_misc.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2014, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +---------------------------------------------------------------------------+ */
9 
10 #pragma once
11 
12 #include <iostream>
13 #include <fstream>
14 #include <sstream> // stringstream
15 
16 namespace mrpt { namespace srba {
17 
18 using namespace std;
19 
20 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
22 {
23  num.clear();
24  sym.next_edge.clear();
25  sym.all_edges.clear();
26 }
27 
28 
29 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
31 {
32  using mrpt::format;
33 
34  s.clear();
35 
36  s +=
37  " From | Shortest path to:=>Next node to move to [Distance] \n"
38  "--------+-----------------------------------------------------------------\n";
39  for (typename next_edge_maps_t::const_iterator it1=sym.next_edge.begin();it1!=sym.next_edge.end();++it1)
40  {
41  s += format(" %6u |",static_cast<unsigned int>(it1->first) );
42 
43  for (map<TKeyFrameID,TSpanTreeEntry>::const_iterator it2=it1->second.begin();it2!=it1->second.end();++it2)
44  s += format(" %5u:=>%5u [%u] |",static_cast<unsigned int>(it2->first), static_cast<unsigned int>(it2->second.next), static_cast<unsigned int>(it2->second.distance));
45 
46  s +=
47  "\n"
48  "--------+-----------------------------------------------------------------\n";
49  }
50 
51  s +=
52  "\n\n"
53  " From | To | Shortest path sequence \n"
54  "--------+--------+--------------------------------------------------------\n";
55  for (typename all_edges_maps_t::const_iterator it1=sym.all_edges.begin();it1!=sym.all_edges.end();++it1)
56  {
57  for (typename map<TKeyFrameID, k2k_edge_vector_t >::const_iterator it2=it1->second.begin();it2!=it1->second.end();++it2)
58  {
59  s += format(" %6u | %6u |",static_cast<unsigned int>(it1->first),static_cast<unsigned int>(it2->first) );
60 
61  const k2k_edge_vector_t & edges = it2->second;
62  for (typename k2k_edge_vector_t::const_iterator it3=edges.begin();it3!=edges.end();++it3)
63  s += format(" [%4u => %4u] ",static_cast<unsigned int>((*it3)->from),static_cast<unsigned int>((*it3)->to) );
64 
65  s+=
66  "\n"
67  "--------+--------+--------------------------------------------------------\n";
68  }
69  }
70 }
71 
72 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
74 {
75  ofstream f;
76  f.open(sFileName.c_str());
77  if (!f.is_open()) return false;
78 
79  string s;
80  this->dump_as_text(s);
81 
82  return !(f << s).fail();
83 }
84 
85 namespace internal
86 {
87  template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
89  set< pair<string,string> > & all_edges,
90  const string &prefix,
91  const TKeyFrameID came_from,
92  const TKeyFrameID root,
93  const map<TKeyFrameID,TSpanTreeEntry> &root_entries,
95  set<TKeyFrameID> &visited,
96  const map<TKeyFrameID,TSpanTreeEntry> &top_root_entries)
97  {
98  visited.insert(root);
99 
100  // All nodes at depth=1
101  for (map<TKeyFrameID,TSpanTreeEntry>::const_iterator it=root_entries.begin();it!=root_entries.end();++it)
102  {
103  if (it->second.distance==1 && top_root_entries.find(it->first)!=top_root_entries.end())
104  {
105  const TKeyFrameID child = it->first;
106  //s << prefix << root << " -> " << prefix << child << ";\n";
107  const string s1 = prefix + mrpt::format("%06u",static_cast<unsigned int>( std::max(root,child) ));
108  const string s2 = prefix + mrpt::format("%06u",static_cast<unsigned int>( std::min(root,child) ));
109  all_edges.insert( make_pair(s1,s2) );
110 
111  if (!visited.count(it->first))
112  {
114  ASSERT_(it_ce != all.end())
115  internal::recursive_print_st_dot(all_edges,prefix,root,child,it_ce->second,all,visited,top_root_entries);
116  }
117  }
118  }
119  }
120 
121 } // end NS "internal"
122 
123 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
124 bool TRBA_Problem_state<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::TSpanningTree::save_as_dot_file(const string &sFileName, const std::vector<TKeyFrameID> &kf_roots_to_save ) const
125 {
126  using mrpt::format;
127 
128  ofstream f;
129  f.open(sFileName.c_str());
130  if (!f.is_open()) return false;
131 
132  vector<next_edge_maps_t::const_iterator> its_to_process;
133 
134  if (kf_roots_to_save.empty())
135  {
136  // All:
137  its_to_process.reserve(sym.next_edge.size());
138  for (next_edge_maps_t::const_iterator it1=sym.next_edge.begin();it1!=sym.next_edge.end();++it1)
139  its_to_process.push_back(it1);
140  }
141  else
142  {
143  for (size_t i=0;i<kf_roots_to_save.size();i++)
144  {
145  next_edge_maps_t::const_iterator it=sym.next_edge.find(kf_roots_to_save[i]);
146  if (it!=sym.next_edge.end()) // silently ignore queries for KFs without a tree
147  its_to_process.push_back(it);
148  }
149  }
150 
151  stringstream s;
152 
153  s << "graph G {\n";
154 
155  map<size_t, set<string> > kfs_by_depth;
156  map<string, size_t> depth_kf;
157 
158  // 1st step: define nodes & their depths:
159  for (size_t k=0;k<its_to_process.size();k++)
160  {
161  const next_edge_maps_t::const_iterator it1=its_to_process[k];
162 
163  const TKeyFrameID root = it1->first;
164  const string sR = format("%06u",static_cast<unsigned int>(root) );
165 
166  const string sNodeDefR = sR + mrpt::format("%06u [label=%u]",static_cast<unsigned int>(root),static_cast<unsigned int>(root));
167  kfs_by_depth[0].insert( sNodeDefR );
168  depth_kf[mrpt::format("%06u%06u",static_cast<unsigned int>(root),static_cast<unsigned int>(root))] = 0;
169 
170  // All nodes at depth=1
171  for (map<TKeyFrameID,TSpanTreeEntry>::const_iterator it=it1->second.begin();it!=it1->second.end();++it)
172  {
173  const string sNodeDef = sR + mrpt::format("%06u [label=%u]",static_cast<unsigned int>(it->first),static_cast<unsigned int>(it->first));
174  kfs_by_depth[it->second.distance].insert( sNodeDef );
175  depth_kf[mrpt::format("%06u%06u",static_cast<unsigned int>(root),static_cast<unsigned int>(it->first))] = it->second.distance;
176  }
177  }
178 
179  for (map<size_t, set<string> >::const_iterator it=kfs_by_depth.begin();it!=kfs_by_depth.end();++it)
180  {
181  //const size_t depth = it->first;
182  const set<string> & sNodes = it->second;
183 
184  s <<
185  "subgraph {\n"
186  " rank = same;\n";
187  for (set<string>::const_iterator itS=sNodes.begin();itS!=sNodes.end();++itS)
188  s << *itS << "\n";
189  s <<"};\n";
190  }
191 
192  // 2nd step: generate list of all edges in all trees:
193  set< pair<string,string> > all_edges;
194 
195  for (size_t k=0;k<its_to_process.size();k++)
196  {
197  const next_edge_maps_t::const_iterator it1=its_to_process[k];
198 
199  const TKeyFrameID root = it1->first;
200 
201  // All nodes at all depths:
202  for (map<TKeyFrameID,TSpanTreeEntry>::const_iterator it=it1->second.begin();it!=it1->second.end();++it)
203  {
204  const TKeyFrameID other = it->first;
205 
206  const TKeyFrameID id1 = std::max(root,other);
207  const TKeyFrameID id2 = std::min(root,other);
208 
209  // Get all edges in the shortest path between them:
210  // (we only store <max,min> since this table is symmetric)
211  typename all_edges_maps_t::const_iterator it_eds_id1 = sym.all_edges.find(id1);
212  ASSERT_(it_eds_id1 != sym.all_edges.end())
213 
214  const std::map<TKeyFrameID, k2k_edge_vector_t> &eds_id1 = it_eds_id1->second;
215  typename std::map<TKeyFrameID, k2k_edge_vector_t>::const_iterator eds_it = eds_id1.find(id2);
216  ASSERT_(eds_it!=eds_id1.end())
217 
218  const k2k_edge_vector_t &eds = eds_it->second;
219 
220  for (size_t i=0;i<eds.size();i++)
221  {
222  const TKeyFrameID to = eds[i]->to;
223  const TKeyFrameID from = eds[i]->from;
224 
225  const string s1 = mrpt::format("%06u%06u",static_cast<unsigned int>(root),static_cast<unsigned int>( std::max(to,from) ));
226  const string s2 = mrpt::format("%06u%06u",static_cast<unsigned int>(root),static_cast<unsigned int>( std::min(to,from) ));
227 
228  all_edges.insert( make_pair(s1,s2) );
229  }
230  }
231  }
232 
233 
234  // And now only draw those at a different depth level:
235  for (set< pair<string,string> >::const_iterator it=all_edges.begin();it!=all_edges.end();++it)
236  s << it->first << " -- " << it->second << ";\n";
237 
238  // And now generate invisible edges between nodes across all depths ("ranks") so graphviz really put them in different physical heights:
239  for (map<size_t, set<string> >::const_iterator it=kfs_by_depth.begin();it!=kfs_by_depth.end();++it)
240  {
241  const set<string> & sNodes = it->second;
242  if (sNodes.empty()) continue; // But shouldn't occur!
243 
244  if (it!=kfs_by_depth.begin())
245  s << " -- ";
246 
247  s << it->second.begin()->substr(0,12) << " ";
248  }
249  if (!kfs_by_depth.empty()) s << " [style=invis];\n";
250 
251  s << "}\n";
252 
253  return !(f << s.str()).fail();
254 }
255 
256 
257 /** Returns min/max and mean/std stats on the number of nodes found on all the spanning trees. Runs in O(N), N=number of keyframes. */
258 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
260  size_t &num_nodes_min,
261  size_t &num_nodes_max,
262  double &num_nodes_mean,
263  double &num_nodes_std) const
264 {
265  num_nodes_min = 0;
266  num_nodes_max = 0;
267  num_nodes_mean = 0;
268  num_nodes_std = 0;
269 
270  std::vector<size_t> num_nodes;
271  num_nodes.reserve(sym.next_edge.size());
272 
273  for (next_edge_maps_t::const_iterator it1=sym.next_edge.begin();it1!=sym.next_edge.end();++it1)
274  num_nodes.push_back( it1->second.size() );
275 
276  mrpt::math::meanAndStd(num_nodes,num_nodes_mean,num_nodes_std);
277  mrpt::math::minimum_maximum(num_nodes, num_nodes_min, num_nodes_max);
278 }
279 
280 
281 } } // end NS
kf2kf_pose_traits< KF2KF_POSE_TYPE >::k2k_edge_vector_t k2k_edge_vector_t
Definition: srba_types.h:478
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
iterator find(const size_t i)
Constant-time find, returning an iterator to the pair or to end() if not found (that is...
STL namespace.
const Scalar * const_iterator
Definition: eigen_plugins.h:24
void recursive_print_st_dot(set< pair< string, string > > &all_edges, const string &prefix, const TKeyFrameID came_from, const TKeyFrameID root, const map< TKeyFrameID, TSpanTreeEntry > &root_entries, const typename TRBA_Problem_state< KF2KF_POSE_TYPE, LM_TYPE, OBS_TYPE, RBA_OPTIONS >::TSpanningTree::next_edge_maps_t &all, set< TKeyFrameID > &visited, const map< TKeyFrameID, TSpanTreeEntry > &top_root_entries)
Definition: spantree_misc.h:88
bool save_as_dot_file(const std::string &sFileName, const std::vector< TKeyFrameID > &kf_roots_to_save=std::vector< TKeyFrameID >()) const
Saves all (or a subset of all) the spanning trees If kf_roots_to_save is left empty, all STs are saved.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
void minimum_maximum(const std::vector< T > &V, T &curMin, T &curMax)
Return the maximum and minimum values of a std::vector.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void get_stats(size_t &num_nodes_min, size_t &num_nodes_max, double &num_nodes_mean, double &num_nodes_std) const
Returns min/max and mean/std stats on the number of nodes found on all the spanning trees...
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
#define ASSERT_(f)
void clear()
Empty all sym & num data.
Definition: spantree_misc.h:21
void dump_as_text(std::string &s) const
Useful for debugging.
Definition: spantree_misc.h:30
bool dump_as_text_to_file(const std::string &sFileName) const
Useful for debugging.
Definition: spantree_misc.h:73
uint64_t TKeyFrameID
Numeric IDs for key-frames (KFs)
Definition: srba_types.h:31



Page generated by Doxygen 1.8.8 for MRPT 1.2.2 SVN:Unversioned directory at Tue Oct 14 02:14:08 UTC 2014