12 namespace mrpt {
namespace srba {
15 #define SYM_ST_SUPER_VERBOSE 0
18 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
23 const bool check_all_obs_are_connected,
32 std::set<TPairKeyFrameID> kfs_with_modified_next_edge;
43 const map<TKeyFrameID,TSpanTreeEntry> & st_ik =
sym.
next_edge[ik];
44 vector<pair<TKeyFrameID,topo_dist_t> > tk;
46 if (it->second.distance<max_depth)
47 tk.push_back( make_pair(it->first,it->second.distance) );
48 tk.push_back( make_pair(ik,0) );
52 const map<TKeyFrameID,TSpanTreeEntry> & st_n =
sym.
next_edge[new_node_id];
53 vector<pair<TKeyFrameID,const TSpanTreeEntry*> > STn;
55 STn.push_back( make_pair(it->first,&it->second) );
56 STn.push_back( pair<TKeyFrameID,const TSpanTreeEntry*>(new_node_id,static_cast<const TSpanTreeEntry*>(NULL)) );
59 for (
size_t r_idx=0;r_idx<STn.size();r_idx++)
65 map<TKeyFrameID,TSpanTreeEntry> & st_r =
sym.
next_edge[r];
72 ste_r2n = &it->second;
76 for (
size_t s_idx=0;s_idx<tk.size();s_idx++)
82 map<TKeyFrameID,TSpanTreeEntry> & st_s =
sym.
next_edge[s];
89 ste_s2ik = &it_ik_inSTs->second;
93 const topo_dist_t new_dist = dist_r2n + dist_s2ik + 1;
97 if (it_s_inSTr != st_r.end())
100 if (new_dist < it_s_inSTr->second.distance)
102 #if SYM_ST_SUPER_VERBOSE
103 cout <<
"ST: Shorter path ST["<<r<<
"]["<<s<<
"].N was "<<it_s_inSTr->second.next <<
" => "<<(ste_r2n ? ste_r2n->
next : ik) <<
"[D:"<<it_s_inSTr->second.distance<<
"=>"<<new_dist<<
"]"<<endl;
104 cout <<
"ST: Shorter path ST["<<s<<
"]["<<r<<
"].N was "<<st_s[r].next <<
" => "<<(ste_s2ik ? ste_s2ik->
next : new_node_id) <<
"[D:"<<st_s[r].distance<<
"=>"<<new_dist<<
"]"<<endl;
108 it_s_inSTr->second.distance = new_dist;
109 it_s_inSTr->second.next = ste_r2n ? ste_r2n->
next : ik;
115 ste_r_inSTs.
next = ste_s2ik ? ste_s2ik->
next : new_node_id;
119 kfs_with_modified_next_edge.insert( make_pair(s,r) );
120 kfs_with_modified_next_edge.insert( make_pair(r,s) );
126 if (new_dist<=max_depth)
128 #if SYM_ST_SUPER_VERBOSE
129 cout <<
"ST: New path ST["<<r<<
"]["<<s<<
"].N ="<<(ste_r2n ? ste_r2n->
next : ik) <<
"[D:"<<dist_r2n + dist_s2ik + 1<<
"]"<<endl;
130 cout <<
"ST: New path ST["<<s<<
"]["<<r<<
"].N ="<<(ste_s2ik ? ste_s2ik->
next : new_node_id) <<
"[D:"<<dist_r2n + dist_s2ik + 1<<
"]"<<endl;
137 ste_s_inSTr.distance = new_dist;
138 ste_s_inSTr.next = ste_r2n ? ste_r2n->
next : ik;
144 ste_r_inSTs.
next = ste_s2ik ? ste_s2ik->
next : new_node_id;
148 kfs_with_modified_next_edge.insert(make_pair(r,s));
149 kfs_with_modified_next_edge.insert(make_pair(s,r));
160 if (check_all_obs_are_connected)
165 std::set<TPairKeyFrameID> pending_checks;
167 for (
size_t i=0;i<obs->size();i++)
182 std::set<TPairKeyFrameID> done_checks;
183 while (!pending_checks.empty())
187 pending_checks.erase(pending_checks.begin());
189 if (done_checks.find(ft)!=done_checks.end())
193 std::map<TKeyFrameID,TSpanTreeEntry> & span_trees_from =
sym.
next_edge[ft.first];
195 if ( span_trees_from.find(ft.second)==span_trees_from.end() )
200 vector<TKeyFrameID> found_path;
202 bool found =
m_parent->find_path_bfs(
207 ASSERT_(found && !found_path.empty())
211 ste.distance = found_path.size();
212 ste.next = *found_path.rbegin();
215 for (
size_t i=0;i<found_path.size();i++)
216 if (found_path[i]!=ft.second)
220 kfs_with_modified_next_edge.insert( ft );
224 done_checks.insert(ft);
230 #if defined(SYM_ST_SUPER_VERBOSE_SAVE_ALL_SPANNING_TREES)
233 const std::string sFil =
mrpt::format(
"debug_spantree_%05i.txt",i);
234 const std::string sFilDot =
mrpt::format(
"debug_spantree_%05i.dot",i);
235 const std::string sFilPng =
mrpt::format(
"debug_spantree_%05i.png",i);
238 ::system(
mrpt::format(
"dot %s -o %s -Tpng",sFilDot.c_str(), sFilPng.c_str() ).c_str());
248 const std::map<TKeyFrameID,TSpanTreeEntry> & Ds =
sym.
next_edge[ kf_id ];
256 const TKeyFrameID from = std::max(dst_kf_id, kf_id);
262 bool path_found =
m_parent->find_path_bfs(from,to, NULL, &path);
267 #if defined(SYM_ST_EXTRA_SECURITY_CHECKS)
273 if (it->second.distance>max_depth)
276 s <<
"CONSISTENCY ERROR: Spanning tree of kf #" << it1->first <<
" has kf #" << it->first
277 <<
" at depth=" << it->second.distance <<
" > Max=" << max_depth << endl;
278 s <<
"After updating symbolic spanning trees for new kf #" << new_node_id <<
" with new edges: ";
279 for (
size_t i=0;i<new_edges.size();i++) s << new_edges[i].first <<
"->" << new_edges[i].second <<
", ";
287 template <class k2k_edge_t>
301 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
305 std::vector<TKeyFrameID> * out_path_IDs,
308 if (out_path_IDs) out_path_IDs->clear();
309 if (out_path_edges) out_path_edges->clear();
310 if (cur_node==trg_node)
return true;
312 std::set<TKeyFrameID> visited;
313 std::queue<TKeyFrameID> pending;
314 std::map<TKeyFrameID,TBFSEntry<k2k_edge_t> > preceding;
317 pending.push(cur_node);
318 visited.insert(cur_node);
319 preceding[cur_node].dist = 0;
321 while (!pending.empty())
329 if (next_kf==trg_node)
333 if (out_path_IDs) out_path_IDs->resize(dist);
334 if (out_path_edges) out_path_edges->resize(dist);
336 while (path_node != cur_node)
339 if (out_path_IDs) (*out_path_IDs)[--dist] = path_node;
341 typename std::map<TKeyFrameID,TBFSEntry<k2k_edge_t> >
::const_iterator it_prec = preceding.find(path_node);
342 ASSERT_(it_prec != preceding.end())
343 path_node = it_prec->second.prev;
345 if (out_path_edges) (*out_path_edges)[--dist] = it_prec->second.prev_edge;
354 for (
size_t i=0;i<kfi.adjacent_k2k_edges.size();i++)
356 const k2k_edge_t* ed = kfi.adjacent_k2k_edges[i];
358 if (!visited.count(new_kf))
360 pending.push(new_kf);
361 visited.insert(new_kf);
365 if (p.
dist>cur_dist+1)
next_edge_maps_t next_edge
Given all interesting spanning tree roots (=SOURCE), this structure holds: map[SOURCE] |-> map[TARGET...
TLandmarkID feat_id
Observed what.
struct mrpt::srba::TRBA_Problem_state::TSpanningTree::TSpanningTreeSym sym
rba_joint_parameterization_traits_t< KF2KF_POSE_TYPE, LM_TYPE, OBS_TYPE >::new_kf_observations_t new_kf_observations_t
vec_t::const_iterator const_iterator
#define THROW_EXCEPTION(msg)
kf2kf_pose_traits< KF2KF_POSE_TYPE >::k2k_edge_t k2k_edge_t
const Scalar * const_iterator
Keyframe-to-keyframe edge: an unknown of the problem.
uint64_t topo_dist_t
Unsigned integral type for topological distances in a graph/tree.
TKeyFrameID next
The next keyframe in the tree.
obs_traits_t::observation_t obs
The argument "POSE_TRAITS" can be any of those defined in srba/models/kf2kf_poses.h (typically, either kf2kf_poses::SE3 or kf2kf_poses::SE2).
Observations, as provided by the user.
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.
void update_symbolic_new_node(const TKeyFrameID new_node_id, const TPairKeyFrameID &new_edge, const topo_dist_t max_depth, const bool check_all_obs_are_connected=false, const new_kf_observations_t *obs=NULL)
Incremental update of spanning trees after the insertion of ONE new node and ONE OR MORE edges...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
all_edges_maps_t all_edges
From the previous data, we can build this alternative, more convenient representation: map[SOURCE] |-...
Used in TRBA_Problem_state.
V getTheOtherFromPair(const V one, const PAIR &p)
Aux function for getting, from a std::pair, "the other" element which is different to a known given o...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
const TRBA_Problem_state< KF2KF_POSE_TYPE, LM_TYPE, OBS_TYPE, RBA_OPTIONS > * m_parent
#define ASSERT_NOT_EQUAL_(__A, __B)
std::pair< TKeyFrameID, TKeyFrameID > TPairKeyFrameID
Used to represent the IDs of a directed edge (first –> second)
bool find_path_bfs(const TKeyFrameID from, const TKeyFrameID to, std::vector< TKeyFrameID > *out_path_IDs, typename kf2kf_pose_traits< KF2KF_POSE_TYPE >::k2k_edge_vector_t *out_path_edges=NULL) const
Auxiliary, brute force (BFS) method for finding the shortest path between any two Keyframes...
keyframe_vector_t keyframes
All key frames (global poses are not included in an RBA problem). Vector indices are "TKeyFrameID" ID...
Information per key-frame needed for RBA.
topo_dist_t distance
Remaining distance until the given target from this point.
bool dump_as_text_to_file(const std::string &sFileName) const
Useful for debugging.
V getTheOtherFromPair2(const V one, const K2K_EDGE &p)
For usage with K2K_EDGE = typename kf2kf_pose_traits
::k2k_edge_t.
uint64_t TKeyFrameID
Numeric IDs for key-frames (KFs)