15 namespace mrpt {
namespace srba {
27 template <
class RBA_ENGINE>
32 static const size_t POSE_DIMS = RBA_ENGINE::kf2kf_pose_type::REL_POSE_DIMS;
33 static const size_t LM_DIMS = RBA_ENGINE::lm_type::LM_DIMS;
38 typename hessian_traits_t::TSparseBlocksHessian_Ap &
HAp;
39 typename hessian_traits_t::TSparseBlocksHessian_f &
Hf;
40 typename hessian_traits_t::TSparseBlocksHessian_Apf &
HApf;
51 const int verbose_level,
53 typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_,
54 typename hessian_traits_t::TSparseBlocksHessian_f &Hf_,
55 typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_,
56 Eigen::VectorXd &minus_grad_,
57 const size_t nUnknowns_k2k_,
58 const size_t nUnknowns_k2f_) :
59 m_verbose_level(verbose_level),
61 HAp(HAp_), Hf(Hf_), HApf(HApf_),
62 minus_grad(minus_grad_),
63 nUnknowns_k2k(nUnknowns_k2k_),
64 nUnknowns_k2f(nUnknowns_k2f_),
65 nUnknowns_scalars( POSE_DIMS*nUnknowns_k2k + LM_DIMS*nUnknowns_k2f ),
66 idx_start_f(POSE_DIMS*nUnknowns_k2k),
67 sS(NULL), sS_is_valid(false)
73 if (sS) {
delete sS; sS=NULL; }
85 else sS->
clear(nUnknowns_scalars,nUnknowns_scalars);
89 for (
size_t i=0;i<nUnknowns_k2k;i++)
91 const typename hessian_traits_t::TSparseBlocksHessian_Ap::col_t & col_i = HAp.getCol(i);
95 if (itRowEntry->first==i)
98 typename hessian_traits_t::TSparseBlocksHessian_Ap::matrix_t sSii = itRowEntry->second.num;
99 for (
size_t k=0;k<POSE_DIMS;k++)
100 sSii.coeffRef(k,k)+=lambda;
106 POSE_DIMS*itRowEntry->first,
108 itRowEntry->second.num );
114 for (
size_t i=0;i<nUnknowns_k2k;i++)
116 const typename hessian_traits_t::TSparseBlocksHessian_Apf::col_t & row_i = HApf.getCol(i);
122 idx_start_f+LM_DIMS*itColEntry->first,
123 itColEntry->second.num );
128 for (
size_t i=0;i<nUnknowns_k2f;i++)
130 const typename hessian_traits_t::TSparseBlocksHessian_f::col_t & col_i = Hf.getCol(i);
134 if (itRowEntry->first==i)
137 typename hessian_traits_t::TSparseBlocksHessian_f::matrix_t sSii = itRowEntry->second.num;
138 for (
size_t k=0;k<LM_DIMS;k++)
139 sSii.coeffRef(k,k)+=lambda;
145 idx_start_f+LM_DIMS*itRowEntry->first,
146 idx_start_f+LM_DIMS*i,
147 itRowEntry->second.num );
166 else ptrCh.get()->update(*sS);
183 ptrCh->backsub(minus_grad,delta_eps);
204 void get_extra_results(
typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t & out_info )
206 out_info.hessian_valid = sS_is_valid;
207 if (sS) sS->
swap(out_info.hessian);
213 template <
class RBA_ENGINE>
218 static const size_t POSE_DIMS = RBA_ENGINE::kf2kf_pose_type::REL_POSE_DIMS;
219 static const size_t LM_DIMS = RBA_ENGINE::lm_type::LM_DIMS;
226 typename hessian_traits_t::TSparseBlocksHessian_Ap &
HAp;
227 typename hessian_traits_t::TSparseBlocksHessian_f &
Hf;
228 typename hessian_traits_t::TSparseBlocksHessian_Apf &
HApf;
237 typename hessian_traits_t::TSparseBlocksHessian_Ap,
238 typename hessian_traits_t::TSparseBlocksHessian_f,
239 typename hessian_traits_t::TSparseBlocksHessian_Apf
245 const int verbose_level,
247 typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_,
248 typename hessian_traits_t::TSparseBlocksHessian_f &Hf_,
249 typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_,
250 Eigen::VectorXd &minus_grad_,
251 const size_t nUnknowns_k2k_,
252 const size_t nUnknowns_k2f_) :
253 m_verbose_level(verbose_level),
254 m_profiler(profiler),
255 nUnknowns_k2k(nUnknowns_k2k_),
256 nUnknowns_k2f(nUnknowns_k2f_),
257 HAp(HAp_),Hf(Hf_),HApf(HApf_),
258 minus_grad(minus_grad_),
259 sS(NULL), sS_is_valid(false),
264 nUnknowns_k2f!=0 ? &minus_grad[POSE_DIMS*nUnknowns_k2k] : NULL
271 if (sS) {
delete sS; sS=NULL; }
286 schur_compl.numeric_build_reduced_system(lambda);
289 if (schur_compl.getNumFeaturesFullRank()!=schur_compl.getNumFeatures())
290 VERBOSE_LEVEL(1) <<
"[OPT] Schur warning: only " << schur_compl.getNumFeaturesFullRank() <<
" out of " << schur_compl.getNumFeatures() <<
" features have full-rank.\n";
294 else sS->
clear(nUnknowns_k2k*POSE_DIMS,nUnknowns_k2k*POSE_DIMS);
300 for (
size_t i=0;i<nUnknowns_k2k;i++)
302 const typename hessian_traits_t::TSparseBlocksHessian_Ap::col_t & col_i = HAp.getCol(i);
306 if (itRowEntry->first==i)
309 typename hessian_traits_t::TSparseBlocksHessian_Ap::matrix_t sSii = itRowEntry->second.num;
310 for (
size_t k=0;k<POSE_DIMS;k++)
311 sSii.coeffRef(k,k)+=lambda;
317 POSE_DIMS*itRowEntry->first,
319 itRowEntry->second.num );
338 else ptrCh.get()->update(*sS);
357 delta_eps.assign(nUnknowns_k2k*POSE_DIMS + nUnknowns_k2f*LM_DIMS, 0);
359 ptrCh->backsub(&minus_grad[0],&delta_eps[0],nUnknowns_k2k*POSE_DIMS);
369 schur_compl.numeric_solve_for_features(
372 nUnknowns_k2f!=0 ? &delta_eps[nUnknowns_k2k*POSE_DIMS] : NULL
385 schur_compl.realize_HAp_changed();
394 return schur_compl.was_ith_feature_invertible(i);
397 void get_extra_results(
typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t & out_info )
399 out_info.hessian_valid = sS_is_valid;
400 if (sS) sS->
swap(out_info.hessian);
406 template <
class RBA_ENGINE>
411 static const size_t POSE_DIMS = RBA_ENGINE::kf2kf_pose_type::REL_POSE_DIMS;
412 static const size_t LM_DIMS = RBA_ENGINE::lm_type::LM_DIMS;
419 typename hessian_traits_t::TSparseBlocksHessian_Ap &
HAp;
420 typename hessian_traits_t::TSparseBlocksHessian_f &
Hf;
421 typename hessian_traits_t::TSparseBlocksHessian_Apf &
HApf;
425 typename hessian_traits_t::TSparseBlocksHessian_Ap,
426 typename hessian_traits_t::TSparseBlocksHessian_f,
427 typename hessian_traits_t::TSparseBlocksHessian_Apf
441 const int verbose_level,
443 typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_,
444 typename hessian_traits_t::TSparseBlocksHessian_f &Hf_,
445 typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_,
446 Eigen::VectorXd &minus_grad_,
447 const size_t nUnknowns_k2k_,
448 const size_t nUnknowns_k2f_) :
449 m_verbose_level(verbose_level),
450 m_profiler(profiler),
451 nUnknowns_k2k(nUnknowns_k2k_),
452 nUnknowns_k2f(nUnknowns_k2f_),
453 HAp(HAp_),Hf(Hf_),HApf(HApf_),
454 minus_grad(minus_grad_),
459 nUnknowns_k2f!=0 ? &minus_grad[POSE_DIMS*nUnknowns_k2k] : NULL
461 denseChol_is_uptodate (false),
462 hessian_is_valid (false)
478 schur_compl.numeric_build_reduced_system(lambda);
481 if (schur_compl.getNumFeaturesFullRank()!=schur_compl.getNumFeatures())
482 VERBOSE_LEVEL(1) <<
"[OPT] Schur warning: only " << schur_compl.getNumFeaturesFullRank() <<
" out of " << schur_compl.getNumFeatures() <<
" features have full-rank.\n";
484 if (!denseChol_is_uptodate)
487 denseH.setZero(nUnknowns_k2k*POSE_DIMS,nUnknowns_k2k*POSE_DIMS);
488 hessian_is_valid =
false;
492 for (
size_t i=0;i<nUnknowns_k2k;i++)
494 const typename hessian_traits_t::TSparseBlocksHessian_Ap::col_t & col_i = HAp.getCol(i);
498 if (itRowEntry->first==i)
501 typename hessian_traits_t::TSparseBlocksHessian_Ap::matrix_t sSii = itRowEntry->second.num;
502 for (
size_t k=0;k<POSE_DIMS;k++)
503 sSii.coeffRef(k,k)+=lambda;
504 denseH.block<POSE_DIMS,POSE_DIMS>(POSE_DIMS*i,POSE_DIMS*i) = sSii;
508 denseH.block<POSE_DIMS,POSE_DIMS>(
509 POSE_DIMS*itRowEntry->first,
511 = itRowEntry->second.num;
517 hessian_is_valid =
true;
522 denseChol = denseH.selfadjointView<Eigen::Upper>().llt();
525 if (denseChol.info()!=Eigen::Success)
531 denseChol_is_uptodate =
true;
541 delta_eps.resize(nUnknowns_k2k*POSE_DIMS + nUnknowns_k2f*LM_DIMS );
542 delta_eps.tail(nUnknowns_k2f*LM_DIMS).setZero();
544 delta_eps.head(nUnknowns_k2k*POSE_DIMS) = denseChol.solve( minus_grad.head(nUnknowns_k2k*POSE_DIMS) );
554 schur_compl.numeric_solve_for_features(
557 nUnknowns_k2f!=0 ? &delta_eps[nUnknowns_k2k*POSE_DIMS] : NULL
567 denseChol_is_uptodate =
false;
573 schur_compl.realize_HAp_changed();
578 return schur_compl.was_ith_feature_invertible(i);
581 void get_extra_results(
typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t & out_info )
583 out_info.hessian_valid = hessian_is_valid;
584 denseH.swap(out_info.hessian);
const size_t nUnknowns_scalars
hessian_traits_t::TSparseBlocksHessian_Apf & HApf
void realize_lambda_changed()
Eigen::VectorXd delta_eps
The result of solving Ax=b will be stored here.
#define DETAILED_PROFILING_ENTER(_STR)
void realize_relinearized()
RBA_ENGINE::hessian_traits_t hessian_traits_t
bool was_ith_feature_invertible(const size_t i)
bool solve(const double lambda)
Auxiliary class to hold the results of a Cholesky factorization of a sparse matrix.
A sparse matrix structure, wrapping T.
bool was_ith_feature_invertible(const size_t i)
const Scalar * const_iterator
bool sS_is_valid
Whether the Hessian was filled in, in sS.
void realize_relinearized()
bool hessian_is_valid
Whether the hessian was correctly evaluated at least once.
void swap(CSparseMatrix &other)
Fast swap contents with another sparse matrix.
hessian_traits_t::TSparseBlocksHessian_Apf & HApf
void get_extra_results(typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t &out_info)
Here, out_info is of type mrpt::srba::options::solver_LM_schur_sparse_cholesky::extra_results_t.
void clear(const size_t nRows=1, const size_t nCols=1)
Erase all previous contents and leave the matrix as a "triplet" ROWS x COLS matrix without any nonzer...
Used in mrpt::math::CSparseMatrix.
void realize_lambda_changed()
const size_t nUnknowns_k2k
solver_engine(const int verbose_level, mrpt::utils::CTimeLogger &profiler, typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_, typename hessian_traits_t::TSparseBlocksHessian_f &Hf_, typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_, Eigen::VectorXd &minus_grad_, const size_t nUnknowns_k2k_, const size_t nUnknowns_k2f_)
Constructor.
bool sS_is_valid
Whether the Hessian was filled in, in sS.
RBA_ENGINE::hessian_traits_t hessian_traits_t
hessian_traits_t::TSparseBlocksHessian_f & Hf
void compressFromTriplet()
ONLY for TRIPLET matrices: convert the matrix in a column-compressed form.
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
Eigen::VectorXd & minus_grad
void get_extra_results(typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t &out_info)
Here, out_info is of type mrpt::srba::options::solver_LM_no_schur_sparse_cholesky::extra_results_t.
SparseCholeskyDecompPtr ptrCh
Cholesky object, as a pointer to reuse it between iterations.
mrpt::math::CSparseMatrix * sS
Sparse Hessian.
void realize_relinearized()
mrpt::math::CSparseMatrix * sS
Sparse Hessian.
const int m_verbose_level
Eigen::VectorXd & minus_grad
const int m_verbose_level
SchurComplement< typename hessian_traits_t::TSparseBlocksHessian_Ap, typename hessian_traits_t::TSparseBlocksHessian_f, typename hessian_traits_t::TSparseBlocksHessian_Apf > schur_compl
bool solve(const double lambda)
#define DETAILED_PROFILING_LEAVE(_STR)
bool was_ith_feature_invertible(const size_t i)
void get_extra_results(typename RBA_ENGINE::rba_options_type::solver_t::extra_results_t &out_info)
Here, out_info is of type mrpt::srba::options::solver_LM_schur_dense_cholesky::extra_results_t.
bool solve(const double lambda)
const size_t nUnknowns_k2k
Eigen::VectorXd & minus_grad
mrpt::utils::CTimeLogger & m_profiler
mrpt::utils::CTimeLogger & m_profiler
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
mrpt::utils::CTimeLogger & m_profiler
Generic solver declaration.
hessian_traits_t::TSparseBlocksHessian_Apf & HApf
hessian_traits_t::TSparseBlocksHessian_f & Hf
SchurComplement< typename hessian_traits_t::TSparseBlocksHessian_Ap, typename hessian_traits_t::TSparseBlocksHessian_f, typename hessian_traits_t::TSparseBlocksHessian_Apf > schur_compl
#define VERBOSE_LEVEL(_LEVEL)
void insert_submatrix(const size_t row, const size_t col, const MATRIX &M)
ONLY for TRIPLET matrices: insert a given matrix (in any of the MRPT formats) at a given location of ...
A generic symbolic and numeric Schur-complement handler for builing reduced systems of equations...
bool denseChol_is_uptodate
A versatile "profiler" that logs the time spent within each pair of calls to enter(X)-leave(X), among other stats.
SparseCholeskyDecompPtr ptrCh
Cholesky object, as a pointer to reuse it between iterations.
solver_engine(const int verbose_level, mrpt::utils::CTimeLogger &profiler, typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_, typename hessian_traits_t::TSparseBlocksHessian_f &Hf_, typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_, Eigen::VectorXd &minus_grad_, const size_t nUnknowns_k2k_, const size_t nUnknowns_k2f_)
Constructor.
solver_engine(const int verbose_level, mrpt::utils::CTimeLogger &profiler, typename hessian_traits_t::TSparseBlocksHessian_Ap &HAp_, typename hessian_traits_t::TSparseBlocksHessian_f &Hf_, typename hessian_traits_t::TSparseBlocksHessian_Apf &HApf_, Eigen::VectorXd &minus_grad_, const size_t nUnknowns_k2k_, const size_t nUnknowns_k2f_)
Constructor.
std::auto_ptr< mrpt::math::CSparseMatrix::CholeskyDecomp > SparseCholeskyDecompPtr
Eigen::VectorXd delta_eps
void realize_lambda_changed()
hessian_traits_t::TSparseBlocksHessian_Ap & HAp
Eigen::LLT< Eigen::MatrixXd, Eigen::Upper > denseChol
hessian_traits_t::TSparseBlocksHessian_Ap & HAp
RBA_ENGINE::hessian_traits_t hessian_traits_t
Eigen::VectorXd delta_eps
The result of solving Ax=b will be stored here.
const int m_verbose_level
hessian_traits_t::TSparseBlocksHessian_f & Hf
hessian_traits_t::TSparseBlocksHessian_Ap & HAp