diff --git a/src/ceres_wrapper/ceres_manager.cpp b/src/ceres_wrapper/ceres_manager.cpp index f2642f433a1166083151779fa20e9ca3a0cefc09..38ba8bea7bc011eb7238e77bdfaa5c7094d3f4d0 100644 --- a/src/ceres_wrapper/ceres_manager.cpp +++ b/src/ceres_wrapper/ceres_manager.cpp @@ -6,7 +6,8 @@ namespace wolf { -CeresManager::CeresManager(ProblemPtr _wolf_problem, const ceres::Solver::Options& _ceres_options) : +CeresManager::CeresManager(ProblemPtr& _wolf_problem, + const ceres::Solver::Options& _ceres_options) : SolverManager(_wolf_problem), ceres_options_(_ceres_options) { @@ -28,46 +29,37 @@ CeresManager::CeresManager(ProblemPtr _wolf_problem, const ceres::Solver::Option problem_options.cost_function_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; problem_options.loss_function_ownership = ceres::TAKE_OWNERSHIP; problem_options.local_parameterization_ownership = ceres::DO_NOT_TAKE_OWNERSHIP; + ceres_problem_ = wolf::make_unique<ceres::Problem>(problem_options); } CeresManager::~CeresManager() { - // std::cout << "ceres residual blocks: " << ceres_problem_->NumResidualBlocks() << std::endl; - // std::cout << "ceres parameter blocks: " << ceres_problem_->NumParameterBlocks() << std::endl; while (!ctr_2_residual_idx_.empty()) removeConstraint(ctr_2_residual_idx_.begin()->first); - // std::cout << "all residuals removed! \n"; } -std::string CeresManager::solve(const unsigned int& _report_level) +std::string CeresManager::solveImpl(const ReportVerbosity report_level) { - //std::cout << "Residual blocks: " << ceres_problem_->NumResidualBlocks() << " Parameter blocks: " << ceres_problem_->NumParameterBlocks() << std::endl; - // update problem update(); - //std::cout << "After Update: Residual blocks: " << ceres_problem_->NumResidualBlocks() << " Parameter blocks: " << ceres_problem_->NumParameterBlocks() << std::endl; - // run Ceres Solver ceres::Solve(ceres_options_, ceres_problem_.get(), &summary_); - //std::cout << "solved" << std::endl; + + std::string report; //return report - if (_report_level == 0) - return std::string(); - else if (_report_level == 1) - return summary_.BriefReport(); - else if (_report_level == 2) - return summary_.FullReport(); - else - throw std::invalid_argument( "Report level should be 0, 1 or 2!" ); + if (report_level == ReportVerbosity::BRIEF) + report = summary_.BriefReport(); + else if (report_level == ReportVerbosity::FULL) + report = summary_.FullReport(); + + return report; } -void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) +void CeresManager::computeCovariances(const CovarianceBlocksToBeComputed _blocks) { - //std::cout << "CeresManager: computing covariances..." << std::endl; - // update problem update(); @@ -80,10 +72,10 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) switch (_blocks) { - case ALL: + case CovarianceBlocksToBeComputed::ALL: { // first create a vector containing all state blocks - std::vector<StateBlockPtr> all_state_blocks, landmark_state_blocks, Frame_state_blocks; + std::vector<StateBlockPtr> all_state_blocks, landmark_state_blocks; //frame state blocks for(auto fr_ptr : wolf_problem_->getTrajectoryPtr()->getFrameList()) if (fr_ptr->isKey()) @@ -102,11 +94,12 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) for (unsigned int j = i; j < all_state_blocks.size(); j++) { state_block_pairs.emplace_back(all_state_blocks[i],all_state_blocks[j]); - double_pairs.emplace_back(all_state_blocks[i]->getPtr(),all_state_blocks[j]->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr(all_state_blocks[i]), + getAssociatedMemBlockPtr(all_state_blocks[j])); } break; } - case ALL_MARGINALS: + case CovarianceBlocksToBeComputed::ALL_MARGINALS: { // first create a vector containing all state blocks for(auto fr_ptr : wolf_problem_->getTrajectoryPtr()->getFrameList()) @@ -117,7 +110,7 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) if (sb) { state_block_pairs.emplace_back(sb, sb2); - double_pairs.emplace_back(sb->getPtr(), sb2->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr(sb), getAssociatedMemBlockPtr(sb2)); if (sb == sb2) break; } @@ -127,7 +120,7 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) for(auto sb2 : l_ptr->getUsedStateBlockVec()) { state_block_pairs.emplace_back(sb, sb2); - double_pairs.emplace_back(sb->getPtr(), sb2->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr(sb), getAssociatedMemBlockPtr(sb2)); if (sb == sb2) break; } // // loop all marginals (PO marginals) @@ -143,7 +136,7 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) // } break; } - case ROBOT_LANDMARKS: + case CovarianceBlocksToBeComputed::ROBOT_LANDMARKS: { //robot-robot auto last_key_frame = wolf_problem_->getLastKeyFramePtr(); @@ -152,9 +145,12 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) state_block_pairs.emplace_back(last_key_frame->getPPtr(), last_key_frame->getOPtr()); state_block_pairs.emplace_back(last_key_frame->getOPtr(), last_key_frame->getOPtr()); - double_pairs.emplace_back(last_key_frame->getPPtr()->getPtr(), last_key_frame->getPPtr()->getPtr()); - double_pairs.emplace_back(last_key_frame->getPPtr()->getPtr(), last_key_frame->getOPtr()->getPtr()); - double_pairs.emplace_back(last_key_frame->getOPtr()->getPtr(), last_key_frame->getOPtr()->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr(last_key_frame->getPPtr()), + getAssociatedMemBlockPtr(last_key_frame->getPPtr())); + double_pairs.emplace_back(getAssociatedMemBlockPtr(last_key_frame->getPPtr()), + getAssociatedMemBlockPtr(last_key_frame->getOPtr())); + double_pairs.emplace_back(getAssociatedMemBlockPtr(last_key_frame->getOPtr()), + getAssociatedMemBlockPtr(last_key_frame->getOPtr())); // landmarks std::vector<StateBlockPtr> landmark_state_blocks; @@ -168,14 +164,17 @@ void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) // robot - landmark state_block_pairs.emplace_back(last_key_frame->getPPtr(), *state_it); state_block_pairs.emplace_back(last_key_frame->getOPtr(), *state_it); - double_pairs.emplace_back(last_key_frame->getPPtr()->getPtr(), (*state_it)->getPtr()); - double_pairs.emplace_back(last_key_frame->getOPtr()->getPtr(), (*state_it)->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr(last_key_frame->getPPtr()), + getAssociatedMemBlockPtr((*state_it))); + double_pairs.emplace_back(getAssociatedMemBlockPtr(last_key_frame->getOPtr()), + getAssociatedMemBlockPtr((*state_it))); // landmark marginal for (auto next_state_it = state_it; next_state_it != landmark_state_blocks.end(); next_state_it++) { state_block_pairs.emplace_back(*state_it, *next_state_it); - double_pairs.emplace_back((*state_it)->getPtr(), (*next_state_it)->getPtr()); + double_pairs.emplace_back(getAssociatedMemBlockPtr((*state_it)), + getAssociatedMemBlockPtr((*next_state_it))); } } } @@ -218,8 +217,9 @@ void CeresManager::computeCovariances(const StateBlockList& st_list) for (auto st_it1 = st_list.begin(); st_it1 != st_list.end(); st_it1++) for (auto st_it2 = st_it1; st_it2 != st_list.end(); st_it2++) { - state_block_pairs.push_back(std::pair<StateBlockPtr, StateBlockPtr>(*st_it1,*st_it2)); - double_pairs.push_back(std::pair<const double*, const double*>((*st_it1)->getPtr(),(*st_it2)->getPtr())); + state_block_pairs.emplace_back(*st_it1, *st_it2); + double_pairs.emplace_back(getAssociatedMemBlockPtr((*st_it1)), + getAssociatedMemBlockPtr((*st_it2))); } //std::cout << "pairs... " << double_pairs.size() << std::endl; @@ -238,72 +238,69 @@ void CeresManager::computeCovariances(const StateBlockList& st_list) std::cout << "WARNING: Couldn't compute covariances!" << std::endl; } -void CeresManager::addConstraint(ConstraintBasePtr _ctr_ptr) +void CeresManager::addConstraint(const ConstraintBasePtr& ctr_ptr) { - ctr_2_costfunction_[_ctr_ptr] = createCostFunction(_ctr_ptr); + auto cost_func_ptr = createCostFunction(ctr_ptr); - // std::cout << "adding constraint " << _ctr_ptr->id() << std::endl; - // std::cout << "constraint pointer " << _ctr_ptr << std::endl; + ctr_2_costfunction_[ctr_ptr] = cost_func_ptr; - if (_ctr_ptr->getApplyLossFunction()) - ctr_2_residual_idx_[_ctr_ptr] = ceres_problem_->AddResidualBlock(ctr_2_costfunction_[_ctr_ptr].get(), new ceres::CauchyLoss(0.5), _ctr_ptr->getStateScalarPtrVector()); - else - ctr_2_residual_idx_[_ctr_ptr] = ceres_problem_->AddResidualBlock(ctr_2_costfunction_[_ctr_ptr].get(), NULL, _ctr_ptr->getStateScalarPtrVector()); + std::vector<Scalar*> res_block_mem; + for (const StateBlockPtr& st : ctr_ptr->getStateBlockPtrVector()) + { + res_block_mem.push_back( getAssociatedMemBlockPtr(st) ); + } + + auto loss_func_ptr = (ctr_ptr->getApplyLossFunction())? + new ceres::CauchyLoss(0.5): nullptr; + + ctr_2_residual_idx_[ctr_ptr] = + ceres_problem_->AddResidualBlock(cost_func_ptr.get(), + loss_func_ptr, res_block_mem); assert(ceres_problem_->NumResidualBlocks() == ctr_2_residual_idx_.size() && "ceres residuals different from wrapper residuals"); } -void CeresManager::removeConstraint(ConstraintBasePtr _ctr_ptr) +void CeresManager::removeConstraint(const ConstraintBasePtr& _ctr_ptr) { - // std::cout << "removing constraint " << _ctr_ptr->id() << std::endl; - assert(ctr_2_residual_idx_.find(_ctr_ptr) != ctr_2_residual_idx_.end()); + ceres_problem_->RemoveResidualBlock(ctr_2_residual_idx_[_ctr_ptr]); ctr_2_residual_idx_.erase(_ctr_ptr); ctr_2_costfunction_.erase(_ctr_ptr); - // std::cout << "removingremoved!" << std::endl; assert(ceres_problem_->NumResidualBlocks() == ctr_2_residual_idx_.size() && "ceres residuals different from wrapper residuals"); } -void CeresManager::addStateBlock(StateBlockPtr _st_ptr) +void CeresManager::addStateBlock(const StateBlockPtr& state_ptr) { - // std::cout << "Adding State Block " << _st_ptr->getPtr() << std::endl; - // std::cout << " size: " << _st_ptr->getSize() << std::endl; - // std::cout << " vector: " << _st_ptr->getVector().transpose() << std::endl; - - if (_st_ptr->hasLocalParametrization()) - { - // std::cout << "Local Parametrization to be added:" << _st_ptr->getLocalParametrizationPtr() << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), _st_ptr->getSize(), new LocalParametrizationWrapper(_st_ptr->getLocalParametrizationPtr())); - } - else - { - // std::cout << "No Local Parametrization to be added" << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), _st_ptr->getSize(), nullptr); - } + /// @todo we create a new object LocalParametrizationWrapper + /// but ceres do not take the ownership, thus this is not deleted properly + auto local_parametrization_ptr = (state_ptr->hasLocalParametrization())? + new LocalParametrizationWrapper(state_ptr->getLocalParametrizationPtr()) : nullptr; + + ceres_problem_->AddParameterBlock(getAssociatedMemBlockPtr(state_ptr), + state_ptr->getSize(), + local_parametrization_ptr); } -void CeresManager::removeStateBlock(StateBlockPtr _st_ptr) +void CeresManager::removeStateBlock(const StateBlockPtr& state_ptr) { - //std::cout << "Removing State Block " << _st_ptr << std::endl; - assert(_st_ptr); - ceres_problem_->RemoveParameterBlock(_st_ptr->getPtr()); + assert(state_ptr); + ceres_problem_->RemoveParameterBlock(getAssociatedMemBlockPtr(state_ptr)); } -void CeresManager::updateStateBlockStatus(StateBlockPtr _st_ptr) +void CeresManager::updateStateBlockStatus(const StateBlockPtr& state_ptr) { - assert(_st_ptr != nullptr); - if (_st_ptr->isFixed()) - ceres_problem_->SetParameterBlockConstant(_st_ptr->getPtr()); + assert(state_ptr != nullptr); + if (state_ptr->isFixed()) + ceres_problem_->SetParameterBlockConstant(getAssociatedMemBlockPtr(state_ptr)); else - ceres_problem_->SetParameterBlockVariable(_st_ptr->getPtr()); + ceres_problem_->SetParameterBlockVariable(getAssociatedMemBlockPtr(state_ptr)); } -ceres::CostFunctionPtr CeresManager::createCostFunction(ConstraintBasePtr _ctr_ptr) +ceres::CostFunctionPtr CeresManager::createCostFunction(const ConstraintBasePtr& _ctr_ptr) { assert(_ctr_ptr != nullptr); - //std::cout << "creating cost function for constraint " << _ctr_ptr->id() << std::endl; // analitic & autodiff jacobian if (_ctr_ptr->getJacobianMethod() == JAC_ANALYTIC || _ctr_ptr->getJacobianMethod() == JAC_AUTO) @@ -314,7 +311,7 @@ ceres::CostFunctionPtr CeresManager::createCostFunction(ConstraintBasePtr _ctr_p return createNumericDiffCostFunction(_ctr_ptr); else - throw std::invalid_argument( "Bad Jacobian Method!" ); + throw std::invalid_argument( "Wrong Jacobian Method!" ); } } // namespace wolf diff --git a/src/ceres_wrapper/ceres_manager.h b/src/ceres_wrapper/ceres_manager.h index d6e86bc136c8d9f3f93cc91504be73b4e00f0946..4651febd6a7fdbd31cae6b0fbaf87876f20f920c 100644 --- a/src/ceres_wrapper/ceres_manager.h +++ b/src/ceres_wrapper/ceres_manager.h @@ -9,7 +9,7 @@ #include "glog/logging.h" //wolf includes -#include "solver_manager.h" +#include "../solver/solver_manager.h" #include "cost_function_wrapper.h" #include "local_parametrization_wrapper.h" #include "create_numeric_diff_cost_function.h" @@ -39,15 +39,17 @@ protected: std::unique_ptr<ceres::Covariance> covariance_; public: - CeresManager(ProblemPtr _wolf_problem, const ceres::Solver::Options& _ceres_options = ceres::Solver::Options()); - ~CeresManager(); + CeresManager(ProblemPtr& _wolf_problem, + const ceres::Solver::Options& _ceres_options + = ceres::Solver::Options()); - virtual std::string solve(const unsigned int& _report_level); + ~CeresManager(); ceres::Solver::Summary getSummary(); - virtual void computeCovariances(CovarianceBlocksToBeComputed _blocks = ROBOT_LANDMARKS); + virtual void computeCovariances(CovarianceBlocksToBeComputed _blocks + = CovarianceBlocksToBeComputed::ROBOT_LANDMARKS); virtual void computeCovariances(const StateBlockList& st_list); @@ -55,17 +57,19 @@ public: private: - virtual void addConstraint(ConstraintBasePtr _ctr_ptr); + std::string solveImpl(const ReportVerbosity report_level) override; + + void addConstraint(const ConstraintBasePtr& ctr_ptr) override; - virtual void removeConstraint(ConstraintBasePtr _ctr_ptr); + void removeConstraint(const ConstraintBasePtr& ctr_ptr) override; - virtual void addStateBlock(StateBlockPtr _st_ptr); + void addStateBlock(const StateBlockPtr& state_ptr) override; - virtual void removeStateBlock(StateBlockPtr _st_ptr); + void removeStateBlock(const StateBlockPtr& state_ptr) override; - virtual void updateStateBlockStatus(StateBlockPtr _st_ptr); + void updateStateBlockStatus(const StateBlockPtr& state_ptr) override; - ceres::CostFunctionPtr createCostFunction(ConstraintBasePtr _ctr_ptr); + ceres::CostFunctionPtr createCostFunction(const ConstraintBasePtr& _ctr_ptr); }; inline ceres::Solver::Summary CeresManager::getSummary()