SRBA: Sparser Relative Bundle Adjustment
srba/impl/sparse_hessian_build_symbolic.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 
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends