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 #include <mrpt/utils/CConfigFileBase.h> // MRPT_LOAD_CONFIG_VAR 00012 00013 namespace srba { 00014 namespace ecps { 00015 00022 struct classic_linear_rba 00023 { 00024 struct parameters_t 00025 { 00026 size_t min_obs_to_loop_closure; 00027 00029 parameters_t() : 00030 min_obs_to_loop_closure ( 4 ) 00031 { } 00032 00034 void loadFromConfigFile(const mrpt::utils::CConfigFileBase & source,const std::string & section) 00035 { 00036 MRPT_LOAD_CONFIG_VAR(min_obs_to_loop_closure,uint64_t,source,section) 00037 } 00038 00040 void saveToConfigFile(mrpt::utils::CConfigFileBase & out,const std::string & section) const 00041 { 00042 out.write(section,"min_obs_to_loop_closure",static_cast<uint64_t>(min_obs_to_loop_closure), /* text width */ 30, 30, "Min. num. of covisible observations to add a loop closure edge"); 00043 } 00044 }; 00045 00049 template <class traits_t,class rba_engine_t> 00050 void eval( 00051 const TKeyFrameID new_kf_id, 00052 const typename traits_t::new_kf_observations_t & obs, 00053 std::vector<TNewEdgeInfo> &new_k2k_edge_ids, 00054 rba_engine_t & rba_engine, 00055 const parameters_t ¶ms) 00056 { 00057 using namespace std; 00058 ASSERT_(new_kf_id>=1) 00059 00060 // (1/2) Always add an edge (n-1) => (n) 00061 // ------------------------------------------- 00062 const typename traits_t::original_kf2kf_pose_t::pose_t init_inv_pose; 00063 00064 TNewEdgeInfo nei1; 00065 nei1.has_approx_init_val = true; // In a linear graph it's a reasonable approx. to make each KF start at the last KF pose, which is what means a null pose init val. 00066 00067 nei1.id = rba_engine.create_kf2kf_edge(new_kf_id, TPairKeyFrameID( new_kf_id-1, new_kf_id), obs, init_inv_pose); 00068 new_k2k_edge_ids.push_back(nei1); 00069 00070 // (2/2) Need to add loop closures? 00071 // ------------------------------------------- 00072 const topo_dist_t min_dist_for_loop_closure = rba_engine.parameters.srba.max_tree_depth + 1; // By definition of loop closure in the SRBA framework 00073 00074 // Go thru all observations and for those already-seen LMs, check the distance between their base KFs and (i_id): 00075 // Make a list of base KFs of my new observations, ordered in descending order by # of shared observations: 00076 base_sorted_lst_t obs_for_each_base_sorted; 00077 srba::internal::make_ordered_list_base_kfs<traits_t,typename rba_engine_t::rba_problem_state_t>(obs, rba_engine.get_rba_state(), obs_for_each_base_sorted); 00078 00079 for (base_sorted_lst_t::const_iterator it=obs_for_each_base_sorted.begin();it!=obs_for_each_base_sorted.end();++it) 00080 { 00081 const size_t num_obs_this_base = it->first; 00082 00083 // Find the distance between "central_kf_id" <=> "new_kf_id" 00084 const TKeyFrameID from_id = new_kf_id; 00085 const TKeyFrameID to_id = it->second; 00086 00087 typename rba_engine_t::rba_problem_state_t::TSpanningTree::next_edge_maps_t::const_iterator it_from = rba_engine.get_rba_state().spanning_tree.sym.next_edge.find(from_id); 00088 00089 topo_dist_t found_distance = numeric_limits<topo_dist_t>::max(); 00090 00091 if (it_from != rba_engine.get_rba_state().spanning_tree.sym.next_edge.end()) { 00092 const map<TKeyFrameID,TSpanTreeEntry> &from_Ds = it_from->second; 00093 map<TKeyFrameID,TSpanTreeEntry>::const_iterator it_to_dist = from_Ds.find(to_id); 00094 if (it_to_dist != from_Ds.end()) 00095 found_distance = it_to_dist->second.distance; 00096 } 00097 else { 00098 // The new KF doesn't still have any edge created to it, that's why we didn't found any spanning tree for it. 00099 // Since this means that the KF is aisolated from the rest of the world, leave the topological distance to infinity. 00100 } 00101 00102 if ( found_distance>=min_dist_for_loop_closure && num_obs_this_base>=params.min_obs_to_loop_closure) 00103 { 00104 // The KF is TOO FAR: We will need to create an additional edge: 00105 TNewEdgeInfo nei; 00106 00107 nei.id = rba_engine.create_kf2kf_edge(new_kf_id, TPairKeyFrameID( to_id, new_kf_id), obs); 00108 00109 nei.has_approx_init_val = false; // By default: Will need to estimate this one 00110 new_k2k_edge_ids.push_back(nei); 00111 00112 mrpt::system::setConsoleColor(mrpt::system::CONCOL_BLUE); 00113 //VERBOSE_LEVEL(2) << "[edge_creation_policy] Created edge #"<< nei.id << ": "<< central_kf_id <<"->"<<new_kf_id << " with #obs: "<< num_obs_this_base<< endl; 00114 mrpt::system::setConsoleColor(mrpt::system::CONCOL_NORMAL); 00115 } 00116 } // end for each base KF 00117 00118 } // end of eval() 00119 00120 }; // end of struct 00121 00122 } } // End of namespaces