SRBA: Sparser Relative Bundle Adjustment
srba/impl/bfs_visitor.h
00001 /* +---------------------------------------------------------------------------+
00002    |                     Mobile Robot Programming Toolkit (MRPT)               |
00003    |                          http://www.mrpt.org/                             |
00004    |                                                                           |
00005    | Copyright (c) 2005-2015, Individual contributors, see AUTHORS file        |
00006    | See: http://www.mrpt.org/Authors - All rights reserved.                   |
00007    | Released under BSD License. See details in http://www.mrpt.org/License    |
00008    +---------------------------------------------------------------------------+ */
00009 
00010 #pragma once
00011 
00012 namespace srba {
00013 
00014 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS>
00015 template <
00016     class KF_VISITOR,
00017     class FEAT_VISITOR,
00018     class K2K_EDGE_VISITOR,
00019     class K2F_EDGE_VISITOR
00020     >
00021 void RbaEngine<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::bfs_visitor(
00022     const TKeyFrameID  root_id,
00023     const topo_dist_t  max_distance,
00024     const bool         rely_on_prebuilt_spanning_trees,
00025     KF_VISITOR       & kf_visitor,
00026     FEAT_VISITOR     & feat_visitor,
00027     K2K_EDGE_VISITOR & k2k_edge_visitor,
00028     K2F_EDGE_VISITOR & k2f_edge_visitor ) const
00029 {
00030     using namespace std;
00031     set<TLandmarkID>   lm_visited;
00032     set<const k2k_edge_t*> k2k_visited;
00033     set<const k2f_edge_t*> k2f_visited;
00034 
00035     if (!rely_on_prebuilt_spanning_trees)
00036     {   // Don't use prebuilt spanning-trees
00037 
00038         set<TKeyFrameID>   kf_visited;
00039         queue<TKeyFrameID> pending;
00040         map<TKeyFrameID,topo_dist_t> distances;
00041 
00042         pending.push(root_id);
00043         kf_visited.insert(root_id);
00044         distances[root_id] = 0;
00045 
00046         while (!pending.empty())
00047         {
00048             const TKeyFrameID next_kf = pending.front();
00049             pending.pop();
00050 
00051             const topo_dist_t cur_dist = distances[next_kf];
00052 
00053             kf_visitor.visit_kf(next_kf,cur_dist);
00054 
00055             // Get all connections of this node:
00056             ASSERTDEB_(next_kf < rba_state.keyframes.size())
00057             const keyframe_info & kfi = rba_state.keyframes[next_kf];
00058 
00059             // Visit all KF2FEAT edges and features themselves:
00060             for (size_t i=0;i<kfi.adjacent_k2f_edges.size();i++)
00061             {
00062                 const k2f_edge_t* ed = kfi.adjacent_k2f_edges[i];
00063                 const TLandmarkID lm_ID = ed->obs.obs.feat_id;
00064                 if (!lm_visited.count(lm_ID))
00065                 {
00066                     if (feat_visitor.visit_filter_feat(lm_ID,cur_dist) )
00067                         feat_visitor.visit_feat(lm_ID,cur_dist);
00068                     lm_visited.insert(lm_ID);
00069                 }
00070                 if (!k2f_visited.count(ed))
00071                 {
00072                     if (k2f_edge_visitor.visit_filter_k2f(next_kf,ed,cur_dist) )
00073                         k2f_edge_visitor.visit_k2f(next_kf,ed,cur_dist);
00074                     k2f_visited.insert(ed);
00075                 }
00076             }
00077 
00078             // Don't explore nearby keyframes if we are already at the maximum distance from root.
00079             if (cur_dist>=max_distance) // At most, we should reach cur_dist==max_distance, but just in case use ">="
00080                 continue;
00081 
00082             // Visit all KF2KF edges and queue nearby keyframes:
00083             for (size_t i=0;i<kfi.adjacent_k2k_edges.size();i++)
00084             {
00085                 const k2k_edge_t* ed = kfi.adjacent_k2k_edges[i];
00086                 const TKeyFrameID new_kf = getTheOtherFromPair2(next_kf, *ed);
00087                 if (!kf_visited.count(new_kf))
00088                 {
00089                     if (kf_visitor.visit_filter_kf(new_kf,cur_dist) )
00090                     {
00091                         pending.push(new_kf);
00092                         distances[new_kf]=cur_dist+1;
00093                     }
00094                     kf_visited.insert(new_kf);
00095                 }
00096                 if (!k2k_visited.count(ed))
00097                 {
00098                     if (k2k_edge_visitor.visit_filter_k2k(next_kf,new_kf,ed,cur_dist) )
00099                         k2k_edge_visitor.visit_k2k(next_kf,new_kf,ed,cur_dist);
00100                     k2k_visited.insert(ed);
00101                 }
00102             }
00103         } // end for each "pending"
00104     }
00105     else
00106     {   // Use prebuilt spanning-trees
00107         const typename rba_problem_state_t::TSpanningTree::TSpanningTreeSym & st_sym = rba_state.spanning_tree.sym;
00108 
00109         typename rba_problem_state_t::TSpanningTree::next_edge_maps_t::const_iterator it_ste = st_sym.next_edge.find(root_id);
00110         if (it_ste == st_sym.next_edge.end())
00111             return; // It might be that this is the first node in the graph/subgraph...
00112 
00113         const std::map<TKeyFrameID,TSpanTreeEntry> & root_ST = it_ste->second;
00114 
00115         // make a list with all the KFs in the root's ST, + the root itself:
00116         std::vector< std::pair<TKeyFrameID,topo_dist_t> >  KFs;
00117         KFs.reserve(root_ST.size()+1);
00118 
00119         KFs.push_back( std::pair<TKeyFrameID,topo_dist_t>(root_id, 0 /* distance */) );
00120         for (typename std::map<TKeyFrameID,TSpanTreeEntry>::const_iterator it=root_ST.begin();it!=root_ST.end();++it)
00121             KFs.push_back( std::pair<TKeyFrameID,topo_dist_t>(it->first,it->second.distance) );
00122 
00123         // Go thru the list:
00124         for (size_t i=0;i<KFs.size();i++)
00125         {
00126             const TKeyFrameID kf_id    = KFs[i].first;
00127             const size_t      cur_dist = KFs[i].second;
00128 
00129             // Don't explore nearby keyframes if we are already at the maximum distance from root.
00130             if (cur_dist>max_distance)
00131                 continue;
00132 
00133             // Visit KF itself:
00134             if (kf_visitor.visit_filter_kf(kf_id,cur_dist) )
00135             {
00136                 kf_visitor.visit_kf(kf_id, cur_dist);
00137             }
00138 
00139             // Get all connections of this KF:
00140             ASSERTDEB_(kf_id < rba_state.keyframes.size())
00141             const keyframe_info & kfi = rba_state.keyframes[kf_id];
00142 
00143             // Visit all KF2FEAT edges and features themselves:
00144             for (size_t i=0;i<kfi.adjacent_k2f_edges.size();i++)
00145             {
00146                 const k2f_edge_t* ed = kfi.adjacent_k2f_edges[i];
00147                 const TLandmarkID lm_ID = ed->obs.obs.feat_id;
00148                 if (!lm_visited.count(lm_ID))
00149                 {
00150                     if (feat_visitor.visit_filter_feat(lm_ID,cur_dist) )
00151                         feat_visitor.visit_feat(lm_ID,cur_dist);
00152                     lm_visited.insert(lm_ID);
00153                 }
00154                 if (!k2f_visited.count(ed))
00155                 {
00156                     if (k2f_edge_visitor.visit_filter_k2f(kf_id,ed,cur_dist) )
00157                         k2f_edge_visitor.visit_k2f(kf_id,ed,cur_dist);
00158                     k2f_visited.insert(ed);
00159                 }
00160             }
00161 
00162             // Visit all KF2KF edges:
00163             for (size_t i=0;i<kfi.adjacent_k2k_edges.size();i++)
00164             {
00165                 const k2k_edge_t* ed = kfi.adjacent_k2k_edges[i];
00166                 const TKeyFrameID new_kf = getTheOtherFromPair2(kf_id, *ed);
00167 
00168                 if (!k2k_visited.count(ed))
00169                 {
00170                     if (k2k_edge_visitor.visit_filter_k2k(kf_id,new_kf,ed,cur_dist) )
00171                         k2k_edge_visitor.visit_k2k(kf_id,new_kf,ed,cur_dist);
00172                     k2k_visited.insert(ed);
00173                 }
00174             }
00175         } // end for each KF node in the ST of root
00176     } // end if-else use STs
00177 }
00178 
00179 
00180 } // end NS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends