SRBA: Sparser Relative Bundle Adjustment
|
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