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 00020 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS> 00021 template <class HESS_Ap, class HESS_f,class HESS_Apf, class JACOB_COLUMN_dh_dAp,class JACOB_COLUMN_dh_df> 00022 void RbaEngine<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::sparse_hessian_build_symbolic( 00023 HESS_Ap & HAp, 00024 HESS_f & Hf, 00025 HESS_Apf & HApf, 00026 const std::vector<JACOB_COLUMN_dh_dAp*> & dh_dAp, 00027 const std::vector<JACOB_COLUMN_dh_df*> & dh_df) 00028 { 00029 typedef typename HESS_Ap::symbolic_t::THessianSymbolicInfoEntry hess_Ap_sym_entry_t; // These are concrete instances of THessianSymbolicInfo<...>::THessianSymbolicInfoEntry 00030 typedef typename HESS_f::symbolic_t::THessianSymbolicInfoEntry hess_f_sym_entry_t; 00031 typedef typename HESS_Apf::symbolic_t::THessianSymbolicInfoEntry hess_Apf_sym_entry_t; 00032 00033 const size_t nUnknowns_k2k = dh_dAp.size(); 00034 const size_t nUnknowns_k2f = dh_df.size(); 00035 00036 // -------------------------------------------------------------------- 00037 // (1) HAp = J_Ap^t * J_Ap 00038 // -------------------------------------------------------------------- 00039 // Only upper-triangular half of U (what is used by Cholesky): 00040 HAp.setColCount (nUnknowns_k2k); 00041 for (size_t i=0;i<nUnknowns_k2k;i++) 00042 { 00043 const JACOB_COLUMN_dh_dAp & col_i = *dh_dAp[i]; 00044 ASSERT_(!col_i.empty()) // I guess this shouldn't happen... 00045 00046 // j=i 00047 // ----- 00048 { 00049 typename HESS_Ap::symbolic_t & Hii_sym = HAp.getCol(i)[i].sym; 00050 00051 for (typename JACOB_COLUMN_dh_dAp::const_iterator it=col_i.begin();it!=col_i.end();++it) 00052 { 00053 const size_t obs_idx = it->first; 00054 00055 Hii_sym.lst_jacob_blocks.push_back( 00056 hess_Ap_sym_entry_t( 00057 &it->second.num, &it->second.num, // J1, J2, 00058 it->second.sym.is_valid,it->second.sym.is_valid, // J1_valid, J2_valid, 00059 obs_idx 00060 ) ); 00061 } 00062 } 00063 00064 // j=[i+1, nUnknowns-1] 00065 // ------------------- 00066 for (size_t j=i+1;j<nUnknowns_k2k;j++) 00067 { 00068 const JACOB_COLUMN_dh_dAp & col_j = *dh_dAp[j]; 00069 ASSERTMSG_(!col_j.empty(),mrpt::format("col_j,i=%u,j=%u empty (nUnknowns_k2k=%u)!",static_cast<unsigned int>(i),static_cast<unsigned int>(j),static_cast<unsigned int>(nUnknowns_k2k))) // I guess this shouldn't happen... 00070 00071 // code below based on "std::set_intersection" 00072 typename JACOB_COLUMN_dh_dAp::const_iterator it_i = col_i.begin(); 00073 typename JACOB_COLUMN_dh_dAp::const_iterator it_j = col_j.begin(); 00074 const typename JACOB_COLUMN_dh_dAp::const_iterator it_i_end = col_i.end(); 00075 const typename JACOB_COLUMN_dh_dAp::const_iterator it_j_end = col_j.end(); 00076 00077 // Don't create the entry in the sparse Hessian until we're sure it's nonzero: 00078 typename HESS_Ap::symbolic_t Hij_sym; 00079 00080 while (it_i!=it_i_end && it_j!=it_j_end) 00081 { 00082 if ( it_i->first < it_j->first ) ++it_i; 00083 else if ( it_j->first < it_i->first ) ++it_j; 00084 else 00085 { 00086 // match between: it_i->first == it_j->first 00087 const size_t obs_idx = it_i->first; 00088 00089 Hij_sym.lst_jacob_blocks.push_back( //std::make_pair(&it_i->second.num, &it_j->second.num) ); 00090 hess_Ap_sym_entry_t( 00091 &it_i->second.num, &it_j->second.num, // J1, J2, 00092 it_i->second.sym.is_valid,it_j->second.sym.is_valid, // J1_valid, J2_valid, 00093 obs_idx 00094 ) ); 00095 00096 // Move: 00097 ++it_i; ++it_j; 00098 } 00099 } 00100 00101 // If it was nonzero, move (swap) to its actual place, created with the [] operator in the std::map<>: 00102 if (!Hij_sym.lst_jacob_blocks.empty()) 00103 Hij_sym.lst_jacob_blocks.swap( HAp.getCol(j)[i].sym.lst_jacob_blocks ); // Caution!! Look: at (j,i), in that order, OK? 00104 00105 } // end for j 00106 } // end for i 00107 00108 // -------------------------------------------------------------------- 00109 // (2) Hf = J_f^t * J_f 00110 // -------------------------------------------------------------------- 00111 // Only upper-triangular half of U (what is used by Cholesky): 00112 Hf.setColCount (nUnknowns_k2f); 00113 for (size_t i=0;i<nUnknowns_k2f;i++) 00114 { 00115 const JACOB_COLUMN_dh_df & col_i = *dh_df[i]; 00116 ASSERT_(!col_i.empty()) // I guess this shouldn't happen... 00117 00118 // j=i 00119 // ----- 00120 { 00121 typename HESS_f::symbolic_t & Hii_sym = Hf.getCol(i)[i].sym; 00122 00123 for (typename JACOB_COLUMN_dh_df::const_iterator it=col_i.begin();it!=col_i.end();++it) 00124 { 00125 const size_t obs_idx = it->first; 00126 00127 Hii_sym.lst_jacob_blocks.push_back( //std::make_pair(&it->second.num, &it->second.num) ); 00128 hess_f_sym_entry_t( 00129 &it->second.num, &it->second.num, // J1, J2, 00130 it->second.sym.is_valid,it->second.sym.is_valid, // J1_valid, J2_valid, 00131 obs_idx 00132 ) ); 00133 } 00134 } 00135 00136 // j=[i+1, nUnknowns-1] 00137 // ------------------- 00138 for (size_t j=i+1;j<nUnknowns_k2f;j++) 00139 { 00140 const JACOB_COLUMN_dh_df & col_j = *dh_df[j]; 00141 ASSERT_(!col_j.empty()) // I guess this shouldn't happen... 00142 00143 // code below based on "std::set_intersection" 00144 typename JACOB_COLUMN_dh_df::const_iterator it_i = col_i.begin(); 00145 typename JACOB_COLUMN_dh_df::const_iterator it_j = col_j.begin(); 00146 const typename JACOB_COLUMN_dh_df::const_iterator it_i_end = col_i.end(); 00147 const typename JACOB_COLUMN_dh_df::const_iterator it_j_end = col_j.end(); 00148 00149 // Don't create the entry in the sparse Hessian until we're sure it's nonzero: 00150 typename HESS_f::symbolic_t Hij_sym; 00151 00152 while (it_i!=it_i_end && it_j!=it_j_end) 00153 { 00154 if ( it_i->first < it_j->first ) ++it_i; 00155 else if ( it_j->first < it_i->first ) ++it_j; 00156 else 00157 { 00158 // match between: it_i->first == it_j->first 00159 const size_t obs_idx = it_i->first; 00160 00161 Hij_sym.lst_jacob_blocks.push_back( //std::make_pair(&it_i->second.num, &it_j->second.num) ); 00162 hess_f_sym_entry_t( 00163 &it_i->second.num, &it_j->second.num, // J1, J2, 00164 it_i->second.sym.is_valid,it_j->second.sym.is_valid, // J1_valid, J2_valid, 00165 obs_idx 00166 ) ); 00167 00168 // Move: 00169 ++it_i; ++it_j; 00170 } 00171 } 00172 00173 // If it was nonzero, move (swap) to its actual place, created with the [] operator in the std::map<>: 00174 if (!Hij_sym.lst_jacob_blocks.empty()) 00175 Hij_sym.lst_jacob_blocks.swap( Hf.getCol(j)[i].sym.lst_jacob_blocks ); // Caution!! Look: at (j,i), in that order, OK? 00176 00177 } // end for j 00178 } // end for i 00179 00180 // -------------------------------------------------------------------- 00181 // (3) HApf = J_Ap^t * J_f 00182 // -------------------------------------------------------------------- 00183 // The entire rectangular matrix (it's NOT symetric!) 00184 00185 // *NOTE* HApf will be stored indices by rows instead of columns!! 00186 00187 //HApf.setColCount(nUnknowns_k2f); 00188 HApf.setColCount(nUnknowns_k2k); // # of ROWS 00189 for (size_t i=0;i<nUnknowns_k2k;i++) // i:row = [0,nUnknowns_k2k-1] 00190 { 00191 const JACOB_COLUMN_dh_dAp & col_i = *dh_dAp[i]; 00192 ASSERT_(!col_i.empty()) // I guess this shouldn't happen... 00193 00194 // j:col = [0,nUnknowns_k2f-1] 00195 for (size_t j=0;j<nUnknowns_k2f;j++) 00196 { 00197 const JACOB_COLUMN_dh_df & col_j = *dh_df[j]; 00198 ASSERT_(!col_j.empty()) // I guess this shouldn't happen... 00199 00200 // code below based on "std::set_intersection" 00201 typename JACOB_COLUMN_dh_dAp::const_iterator it_i = col_i.begin(); 00202 typename JACOB_COLUMN_dh_df::const_iterator it_j = col_j.begin(); 00203 const typename JACOB_COLUMN_dh_dAp::const_iterator it_i_end = col_i.end(); 00204 const typename JACOB_COLUMN_dh_df::const_iterator it_j_end = col_j.end(); 00205 00206 // Don't create the entry in the sparse Hessian until we're sure it's nonzero: 00207 typename HESS_Apf::symbolic_t Hij_sym; 00208 00209 while (it_i!=it_i_end && it_j!=it_j_end) 00210 { 00211 if ( it_i->first < it_j->first ) ++it_i; 00212 else if ( it_j->first < it_i->first ) ++it_j; 00213 else 00214 { 00215 // match between: it_i->first == it_j->first 00216 const size_t obs_idx = it_i->first; 00217 00218 Hij_sym.lst_jacob_blocks.push_back( 00219 hess_Apf_sym_entry_t( 00220 &it_i->second.num, &it_j->second.num, // J1, J2, 00221 it_i->second.sym.is_valid,it_j->second.sym.is_valid, // J1_valid, J2_valid, 00222 obs_idx 00223 ) ); 00224 00225 // Move: 00226 ++it_i; ++it_j; 00227 } 00228 } 00229 00230 // If it was nonzero, move (swap) to its actual place, created with the [] operator in the std::map<>: 00231 if (!Hij_sym.lst_jacob_blocks.empty()) 00232 Hij_sym.lst_jacob_blocks.swap( HApf.getCol(i)[j].sym.lst_jacob_blocks ); // (i,j) because it's stored indices by rows instead of columns! 00233 00234 } // end for j 00235 } // end for i 00236 00237 } 00238 00239 } // end NS