diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c0019cfcf05886f2350a29c8e6320001cdfa89e7..c8774da932baa28806790fc8b1d8743f5caa4a0a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -194,6 +194,7 @@ SET(HDRS_BASE local_parametrization_quaternion.h local_parametrization_homogeneous.h logging.h + make_unique.h map_base.h motion_buffer.h node_base.h @@ -202,6 +203,7 @@ SET(HDRS_BASE processor_base.h processor_capture_holder.h processor_factory.h + processor_logging.h processor_loopclosure_base.h processor_motion.h processor_tracker.h @@ -354,11 +356,14 @@ SET(SRCS_DTASSC data_association/association_nnls.cpp ) +# Add the solver sub-directory +add_subdirectory(solver) + #optional HDRS and SRCS IF (Ceres_FOUND) SET(HDRS_WRAPPER ceres_wrapper/sparse_utils.h - ceres_wrapper/solver_manager.h + #ceres_wrapper/solver_manager.h ceres_wrapper/ceres_manager.h #ceres_wrapper/qr_manager.h ceres_wrapper/cost_function_wrapper.h @@ -366,7 +371,7 @@ IF (Ceres_FOUND) ceres_wrapper/local_parametrization_wrapper.h ) SET(SRCS_WRAPPER - ceres_wrapper/solver_manager.cpp + #ceres_wrapper/solver_manager.cpp ceres_wrapper/ceres_manager.cpp #ceres_wrapper/qr_manager.cpp ceres_wrapper/local_parametrization_wrapper.cpp @@ -447,9 +452,9 @@ IF (cereal_FOUND) ADD_SUBDIRECTORY(serialization/cereal) ENDIF(cereal_FOUND) -#IF (Suitesparse_FOUND) -# ADD_SUBDIRECTORY(solver) -#ENDIF(Suitesparse_FOUND) +IF (Suitesparse_FOUND) + ADD_SUBDIRECTORY(solver_suitesparse) +ENDIF(Suitesparse_FOUND) # LEAVE YAML FILES ALWAYS IN THE LAST POSITION !! IF(YAMLCPP_FOUND) @@ -490,6 +495,7 @@ ADD_LIBRARY(${PROJECT_NAME} ${SRCS_SENSOR} ${SRCS_PROCESSOR} #${SRCS_DTASSC} + ${SRCS_SOLVER} ${SRCS_WRAPPER} ) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${CMAKE_THREAD_LIBS_INIT}) @@ -550,11 +556,12 @@ INSTALL(FILES ${HDRS_PROCESSOR} DESTINATION include/iri-algorithms/wolf/processors) INSTALL(FILES ${HDRS_WRAPPER} DESTINATION include/iri-algorithms/wolf/ceres_wrapper) -#INSTALL(FILES ${HDRS_SOLVER} -# DESTINATION include/iri-algorithms/wolf/solver) +#INSTALL(FILES ${HDRS_SOLVER_SUITESPARSE} +# DESTINATION include/iri-algorithms/wolf/solver_suitesparse) +INSTALL(FILES ${HDRS_SOLVER} + DESTINATION include/iri-algorithms/wolf/solver) INSTALL(FILES ${HDRS_SERIALIZATION} DESTINATION include/iri-algorithms/wolf/serialization) - INSTALL(FILES "${CMAKE_SOURCE_DIR}/cmake_modules/Findwolf.cmake" DESTINATION "lib/cmake/${PROJECT_NAME}") diff --git a/src/ceres_wrapper/ceres_manager.cpp b/src/ceres_wrapper/ceres_manager.cpp index 556e1fa03d02c007ef0b0ed4b09c68e3aa444e42..f37b2377b391564d10a6163ca95d89a5823c480c 100644 --- a/src/ceres_wrapper/ceres_manager.cpp +++ b/src/ceres_wrapper/ceres_manager.cpp @@ -3,323 +3,321 @@ #include "../trajectory_base.h" #include "../map_base.h" #include "../landmark_base.h" +#include "../make_unique.h" namespace wolf { -CeresManager::CeresManager(ProblemPtr _wolf_problem, const ceres::Solver::Options& _ceres_options) : - SolverManager(_wolf_problem), - ceres_options_(_ceres_options) +CeresManager::CeresManager(ProblemPtr& _wolf_problem, + const ceres::Solver::Options& _ceres_options) : + SolverManager(_wolf_problem), + ceres_options_(_ceres_options) { - ceres::Covariance::Options covariance_options; - #if CERES_VERSION_MINOR >= 13 - covariance_options.algorithm_type = ceres::SPARSE_QR;//ceres::DENSE_SVD; - covariance_options.sparse_linear_algebra_library_type = ceres::SUITE_SPARSE; - #elif CERES_VERSION_MINOR >= 10 - covariance_options.algorithm_type = ceres::SUITE_SPARSE_QR;//ceres::DENSE_SVD; - #else - covariance_options.algorithm_type = ceres::SPARSE_QR;//ceres::DENSE_SVD; - #endif - covariance_options.num_threads = 1; - covariance_options.apply_loss_function = false; - //covariance_options.null_space_rank = -1; - covariance_ = new ceres::Covariance(covariance_options); - - ceres::Problem::Options problem_options; - 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_ = new ceres::Problem(problem_options); + ceres::Covariance::Options covariance_options; +#if CERES_VERSION_MINOR >= 13 + covariance_options.algorithm_type = ceres::SPARSE_QR;//ceres::DENSE_SVD; + covariance_options.sparse_linear_algebra_library_type = ceres::SUITE_SPARSE; +#elif CERES_VERSION_MINOR >= 10 + covariance_options.algorithm_type = ceres::SUITE_SPARSE_QR;//ceres::DENSE_SVD; +#else + covariance_options.algorithm_type = ceres::SPARSE_QR;//ceres::DENSE_SVD; +#endif + covariance_options.num_threads = 1; + covariance_options.apply_loss_function = false; + //covariance_options.null_space_rank = -1; + covariance_ = wolf::make_unique<ceres::Covariance>(covariance_options); + + ceres::Problem::Options problem_options; + 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"; - - delete covariance_; - //std::cout << "covariance deleted! \n"; - delete ceres_problem_; - //std::cout << "ceres problem deleted! \n"; + while (!ctr_2_residual_idx_.empty()) + removeConstraint(ctr_2_residual_idx_.begin()->first); } -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_, &summary_); - //std::cout << "solved" << std::endl; - - //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!" ); -} - -void CeresManager::computeCovariances(CovarianceBlocksToBeComputed _blocks) -{ - //std::cout << "CeresManager: computing covariances..." << std::endl; + // run Ceres Solver + ceres::Solve(ceres_options_, ceres_problem_.get(), &summary_); - // update problem - update(); + std::string report; - // CLEAR STORED COVARIANCE BLOCKS IN WOLF PROBLEM - wolf_problem_->clearCovariance(); + //return report + if (report_level == ReportVerbosity::BRIEF) + report = summary_.BriefReport(); + else if (report_level == ReportVerbosity::FULL) + report = summary_.FullReport(); - // CREATE DESIRED COVARIANCES LIST - std::vector<std::pair<StateBlockPtr, StateBlockPtr>> state_block_pairs; - std::vector<std::pair<const double*, const double*>> double_pairs; + return report; +} - switch (_blocks) +void CeresManager::computeCovariances(const CovarianceBlocksToBeComputed _blocks) +{ + // update problem + update(); + + // CLEAR STORED COVARIANCE BLOCKS IN WOLF PROBLEM + wolf_problem_->clearCovariance(); + + // CREATE DESIRED COVARIANCES LIST + std::vector<std::pair<StateBlockPtr, StateBlockPtr>> state_block_pairs; + std::vector<std::pair<const double*, const double*>> double_pairs; + + switch (_blocks) + { + case CovarianceBlocksToBeComputed::ALL: + { + // first create a vector containing all 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()) + for (auto sb : fr_ptr->getStateBlockVec()) + if (sb) + all_state_blocks.push_back(sb); + + // landmark state blocks + for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) { - case ALL: - { - // first create a vector containing all state blocks - std::vector<StateBlockPtr> all_state_blocks, landmark_state_blocks, Frame_state_blocks; - //frame state blocks - for(auto fr_ptr : wolf_problem_->getTrajectoryPtr()->getFrameList()) - if (fr_ptr->isKey()) - for (auto sb : fr_ptr->getStateBlockVec()) - if (sb) - all_state_blocks.push_back(sb); - - // landmark state blocks - for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) - { - landmark_state_blocks = l_ptr->getUsedStateBlockVec(); - all_state_blocks.insert(all_state_blocks.end(), landmark_state_blocks.begin(), landmark_state_blocks.end()); - } - // double loop all against all (without repetitions) - for (unsigned int i = 0; i < all_state_blocks.size(); i++) - 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()); - } - break; - } - case ALL_MARGINALS: + landmark_state_blocks = l_ptr->getUsedStateBlockVec(); + all_state_blocks.insert(all_state_blocks.end(), landmark_state_blocks.begin(), landmark_state_blocks.end()); + } + // double loop all against all (without repetitions) + for (unsigned int i = 0; i < all_state_blocks.size(); i++) + 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(getAssociatedMemBlockPtr(all_state_blocks[i]), + getAssociatedMemBlockPtr(all_state_blocks[j])); + } + break; + } + case CovarianceBlocksToBeComputed::ALL_MARGINALS: + { + // first create a vector containing all state blocks + for(auto fr_ptr : wolf_problem_->getTrajectoryPtr()->getFrameList()) + if (fr_ptr->isKey()) + for (auto sb : fr_ptr->getStateBlockVec()) + if (sb) + for(auto sb2 : fr_ptr->getStateBlockVec()) + if (sb) + { + state_block_pairs.emplace_back(sb, sb2); + double_pairs.emplace_back(getAssociatedMemBlockPtr(sb), getAssociatedMemBlockPtr(sb2)); + if (sb == sb2) break; + } + + // landmark state blocks + for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) + for (auto sb : l_ptr->getUsedStateBlockVec()) + for(auto sb2 : l_ptr->getUsedStateBlockVec()) { - // first create a vector containing all state blocks - for(auto fr_ptr : wolf_problem_->getTrajectoryPtr()->getFrameList()) - if (fr_ptr->isKey()) - for (auto sb : fr_ptr->getStateBlockVec()) - if (sb) - for(auto sb2 : fr_ptr->getStateBlockVec()) - if (sb) - { - state_block_pairs.emplace_back(sb, sb2); - double_pairs.emplace_back(sb->getPtr(), sb2->getPtr()); - if (sb == sb2) break; - } - - // landmark state blocks - for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) - for (auto sb : l_ptr->getUsedStateBlockVec()) - for(auto sb2 : l_ptr->getUsedStateBlockVec()) - { - state_block_pairs.emplace_back(sb, sb2); - double_pairs.emplace_back(sb->getPtr(), sb2->getPtr()); - if (sb == sb2) break; - } -// // loop all marginals (PO marginals) -// for (unsigned int i = 0; 2*i+1 < all_state_blocks.size(); i++) -// { -// state_block_pairs.emplace_back(all_state_blocks[2*i],all_state_blocks[2*i]); -// state_block_pairs.emplace_back(all_state_blocks[2*i],all_state_blocks[2*i+1]); -// state_block_pairs.emplace_back(all_state_blocks[2*i+1],all_state_blocks[2*i+1]); -// -// double_pairs.emplace_back(all_state_blocks[2*i]->getPtr(),all_state_blocks[2*i]->getPtr()); -// double_pairs.emplace_back(all_state_blocks[2*i]->getPtr(),all_state_blocks[2*i+1]->getPtr()); -// double_pairs.emplace_back(all_state_blocks[2*i+1]->getPtr(),all_state_blocks[2*i+1]->getPtr()); -// } - break; + state_block_pairs.emplace_back(sb, sb2); + double_pairs.emplace_back(getAssociatedMemBlockPtr(sb), getAssociatedMemBlockPtr(sb2)); + if (sb == sb2) break; } - case ROBOT_LANDMARKS: + // // loop all marginals (PO marginals) + // for (unsigned int i = 0; 2*i+1 < all_state_blocks.size(); i++) + // { + // state_block_pairs.emplace_back(all_state_blocks[2*i],all_state_blocks[2*i]); + // state_block_pairs.emplace_back(all_state_blocks[2*i],all_state_blocks[2*i+1]); + // state_block_pairs.emplace_back(all_state_blocks[2*i+1],all_state_blocks[2*i+1]); + // + // double_pairs.emplace_back(all_state_blocks[2*i]->getPtr(),all_state_blocks[2*i]->getPtr()); + // double_pairs.emplace_back(all_state_blocks[2*i]->getPtr(),all_state_blocks[2*i+1]->getPtr()); + // double_pairs.emplace_back(all_state_blocks[2*i+1]->getPtr(),all_state_blocks[2*i+1]->getPtr()); + // } + break; + } + case CovarianceBlocksToBeComputed::ROBOT_LANDMARKS: + { + //robot-robot + auto last_key_frame = wolf_problem_->getLastKeyFramePtr(); + + state_block_pairs.emplace_back(last_key_frame->getPPtr(), last_key_frame->getPPtr()); + 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(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; + for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) + { + // load state blocks vector + landmark_state_blocks = l_ptr->getUsedStateBlockVec(); + + for (auto state_it = landmark_state_blocks.begin(); state_it != landmark_state_blocks.end(); state_it++) + { + // 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(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++) { - //robot-robot - auto last_key_frame = wolf_problem_->getLastKeyFramePtr(); - - state_block_pairs.emplace_back(last_key_frame->getPPtr(), last_key_frame->getPPtr()); - 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()); - - // landmarks - std::vector<StateBlockPtr> landmark_state_blocks; - for(auto l_ptr : wolf_problem_->getMapPtr()->getLandmarkList()) - { - // load state blocks vector - landmark_state_blocks = l_ptr->getUsedStateBlockVec(); - - for (auto state_it = landmark_state_blocks.begin(); state_it != landmark_state_blocks.end(); state_it++) - { - // 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()); - - // 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()); - } - } - } - break; + state_block_pairs.emplace_back(*state_it, *next_state_it); + double_pairs.emplace_back(getAssociatedMemBlockPtr((*state_it)), + getAssociatedMemBlockPtr((*next_state_it))); } + } } - //std::cout << "pairs... " << double_pairs.size() << std::endl; - - // COMPUTE DESIRED COVARIANCES - if (covariance_->Compute(double_pairs, ceres_problem_)) + break; + } + } + //std::cout << "pairs... " << double_pairs.size() << std::endl; + + // COMPUTE DESIRED COVARIANCES + if (covariance_->Compute(double_pairs, ceres_problem_.get())) + { + // STORE DESIRED COVARIANCES + for (unsigned int i = 0; i < double_pairs.size(); i++) { - // STORE DESIRED COVARIANCES - for (unsigned int i = 0; i < double_pairs.size(); i++) - { - Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cov(state_block_pairs[i].first->getSize(),state_block_pairs[i].second->getSize()); - covariance_->GetCovarianceBlock(double_pairs[i].first, double_pairs[i].second, cov.data()); - wolf_problem_->addCovarianceBlock(state_block_pairs[i].first, state_block_pairs[i].second, cov); - //std::cout << "getted covariance " << std::endl << cov << std::endl; - } + Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cov(state_block_pairs[i].first->getSize(),state_block_pairs[i].second->getSize()); + covariance_->GetCovarianceBlock(double_pairs[i].first, double_pairs[i].second, cov.data()); + wolf_problem_->addCovarianceBlock(state_block_pairs[i].first, state_block_pairs[i].second, cov); + //std::cout << "getted covariance " << std::endl << cov << std::endl; } - else - std::cout << "WARNING: Couldn't compute covariances!" << std::endl; + } + else + std::cout << "WARNING: Couldn't compute covariances!" << std::endl; } void CeresManager::computeCovariances(const StateBlockList& st_list) { - //std::cout << "CeresManager: computing covariances..." << std::endl; + //std::cout << "CeresManager: computing covariances..." << std::endl; - // update problem - update(); + // update problem + update(); - // CLEAR STORED COVARIANCE BLOCKS IN WOLF PROBLEM - wolf_problem_->clearCovariance(); + // CLEAR STORED COVARIANCE BLOCKS IN WOLF PROBLEM + wolf_problem_->clearCovariance(); - // CREATE DESIRED COVARIANCES LIST - std::vector<std::pair<StateBlockPtr, StateBlockPtr>> state_block_pairs; - std::vector<std::pair<const double*, const double*>> double_pairs; + // CREATE DESIRED COVARIANCES LIST + std::vector<std::pair<StateBlockPtr, StateBlockPtr>> state_block_pairs; + std::vector<std::pair<const double*, const double*>> double_pairs; - // double loop all against all (without repetitions) - 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())); - } + // double loop all against all (without repetitions) + 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.emplace_back(*st_it1, *st_it2); + double_pairs.emplace_back(getAssociatedMemBlockPtr((*st_it1)), + getAssociatedMemBlockPtr((*st_it2))); + } - //std::cout << "pairs... " << double_pairs.size() << std::endl; + //std::cout << "pairs... " << double_pairs.size() << std::endl; - // COMPUTE DESIRED COVARIANCES - if (covariance_->Compute(double_pairs, ceres_problem_)) - // STORE DESIRED COVARIANCES - for (unsigned int i = 0; i < double_pairs.size(); i++) - { - Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cov(state_block_pairs[i].first->getSize(),state_block_pairs[i].second->getSize()); - covariance_->GetCovarianceBlock(double_pairs[i].first, double_pairs[i].second, cov.data()); - wolf_problem_->addCovarianceBlock(state_block_pairs[i].first, state_block_pairs[i].second, cov); - //std::cout << "getted covariance " << std::endl << cov << std::endl; - } - else - std::cout << "WARNING: Couldn't compute covariances!" << std::endl; + // COMPUTE DESIRED COVARIANCES + if (covariance_->Compute(double_pairs, ceres_problem_.get())) + // STORE DESIRED COVARIANCES + for (unsigned int i = 0; i < double_pairs.size(); i++) + { + Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cov(state_block_pairs[i].first->getSize(),state_block_pairs[i].second->getSize()); + covariance_->GetCovarianceBlock(double_pairs[i].first, double_pairs[i].second, cov.data()); + wolf_problem_->addCovarianceBlock(state_block_pairs[i].first, state_block_pairs[i].second, cov); + //std::cout << "getted covariance " << std::endl << cov << std::endl; + } + else + 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); + + ctr_2_costfunction_[ctr_ptr] = cost_func_ptr; -// std::cout << "adding constraint " << _ctr_ptr->id() << std::endl; -// std::cout << "constraint pointer " << _ctr_ptr << std::endl; + std::vector<Scalar*> res_block_mem; + res_block_mem.reserve(ctr_ptr->getStateBlockPtrVector().size()); + for (const StateBlockPtr& st : ctr_ptr->getStateBlockPtrVector()) + { + res_block_mem.emplace_back( getAssociatedMemBlockPtr(st) ); + } - 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()); + auto loss_func_ptr = (ctr_ptr->getApplyLossFunction())? + new ceres::CauchyLoss(0.5): nullptr; - assert(ceres_problem_->NumResidualBlocks() == ctr_2_residual_idx_.size() && "ceres residuals different from wrapper residuals"); + 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()); - 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); + 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"); + 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; + ceres::LocalParameterization* local_parametrization_ptr = nullptr; - 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); - } + if (state_ptr->hasLocalParametrization() && + state_blocks_local_param_.find(state_ptr)==state_blocks_local_param_.end()) + { + auto p = state_blocks_local_param_.emplace( + state_ptr, + std::make_shared<LocalParametrizationWrapper>(state_ptr->getLocalParametrizationPtr())); + + local_parametrization_ptr = p.first->second.get(); + } + + 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()); - else - ceres_problem_->SetParameterBlockVariable(_st_ptr->getPtr()); + assert(state_ptr != nullptr); + if (state_ptr->isFixed()) + ceres_problem_->SetParameterBlockConstant(getAssociatedMemBlockPtr(state_ptr)); + else + 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; + assert(_ctr_ptr != nullptr); - // analitic & autodiff jacobian - if (_ctr_ptr->getJacobianMethod() == JAC_ANALYTIC || _ctr_ptr->getJacobianMethod() == JAC_AUTO) - return std::make_shared<CostFunctionWrapper>(_ctr_ptr); + // analitic & autodiff jacobian + if (_ctr_ptr->getJacobianMethod() == JAC_ANALYTIC || _ctr_ptr->getJacobianMethod() == JAC_AUTO) + return std::make_shared<CostFunctionWrapper>(_ctr_ptr); - // numeric jacobian - else if (_ctr_ptr->getJacobianMethod() == JAC_NUMERIC) - return createNumericDiffCostFunction(_ctr_ptr); + // numeric jacobian + else if (_ctr_ptr->getJacobianMethod() == JAC_NUMERIC) + return createNumericDiffCostFunction(_ctr_ptr); - else - throw std::invalid_argument( "Bad Jacobian Method!" ); + else + 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 c36144c4ed60cb8f63e840475f3e90be138efd1e..2e1e0cb998df70e5ac6e42968edc62a6b326d151 100644 --- a/src/ceres_wrapper/ceres_manager.h +++ b/src/ceres_wrapper/ceres_manager.h @@ -7,13 +7,13 @@ #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" namespace ceres { - typedef std::shared_ptr<CostFunction> CostFunctionPtr; +typedef std::shared_ptr<CostFunction> CostFunctionPtr; } namespace wolf { @@ -26,52 +26,60 @@ WOLF_PTR_TYPEDEFS(CeresManager); class CeresManager : public SolverManager { - protected: - std::map<ConstraintBasePtr, ceres::ResidualBlockId> ctr_2_residual_idx_; - std::map<ConstraintBasePtr, ceres::CostFunctionPtr> ctr_2_costfunction_; - ceres::Problem* ceres_problem_; - ceres::Solver::Options ceres_options_; - ceres::Covariance* covariance_; - ceres::Solver::Summary summary_; +protected: - public: - CeresManager(ProblemPtr _wolf_problem, const ceres::Solver::Options& _ceres_options = ceres::Solver::Options()); + std::map<ConstraintBasePtr, ceres::ResidualBlockId> ctr_2_residual_idx_; + std::map<ConstraintBasePtr, ceres::CostFunctionPtr> ctr_2_costfunction_; - ~CeresManager(); + std::map<StateBlockPtr, LocalParametrizationWrapperPtr> state_blocks_local_param_; - virtual std::string solve(const unsigned int& _report_level); + ceres::Solver::Options ceres_options_; + ceres::Solver::Summary summary_; + std::unique_ptr<ceres::Problem> ceres_problem_; + std::unique_ptr<ceres::Covariance> covariance_; - ceres::Solver::Summary getSummary(); +public: - virtual void computeCovariances(CovarianceBlocksToBeComputed _blocks = ROBOT_LANDMARKS); + CeresManager(ProblemPtr& _wolf_problem, + const ceres::Solver::Options& _ceres_options + = ceres::Solver::Options()); - virtual void computeCovariances(const StateBlockList& st_list); + ~CeresManager(); - ceres::Solver::Options& getSolverOptions(); + ceres::Solver::Summary getSummary(); - private: + virtual void computeCovariances(CovarianceBlocksToBeComputed _blocks + = CovarianceBlocksToBeComputed::ROBOT_LANDMARKS); - virtual void addConstraint(ConstraintBasePtr _ctr_ptr); + virtual void computeCovariances(const StateBlockList& st_list); - virtual void removeConstraint(ConstraintBasePtr _ctr_ptr); + ceres::Solver::Options& getSolverOptions(); - virtual void addStateBlock(StateBlockPtr _st_ptr); +private: - virtual void removeStateBlock(StateBlockPtr _st_ptr); + std::string solveImpl(const ReportVerbosity report_level) override; - virtual void updateStateBlockStatus(StateBlockPtr _st_ptr); + void addConstraint(const ConstraintBasePtr& ctr_ptr) override; - ceres::CostFunctionPtr createCostFunction(ConstraintBasePtr _ctr_ptr); + void removeConstraint(const ConstraintBasePtr& ctr_ptr) override; + + void addStateBlock(const StateBlockPtr& state_ptr) override; + + void removeStateBlock(const StateBlockPtr& state_ptr) override; + + void updateStateBlockStatus(const StateBlockPtr& state_ptr) override; + + ceres::CostFunctionPtr createCostFunction(const ConstraintBasePtr& _ctr_ptr); }; inline ceres::Solver::Summary CeresManager::getSummary() { - return summary_; + return summary_; } inline ceres::Solver::Options& CeresManager::getSolverOptions() { - return ceres_options_; + return ceres_options_; } } // namespace wolf diff --git a/src/ceres_wrapper/local_parametrization_wrapper.h b/src/ceres_wrapper/local_parametrization_wrapper.h index d81b2b3d4476bbd31c687d727f2eb89627b03692..1d81970a963c374cf91a5b283cf443774cb05729 100644 --- a/src/ceres_wrapper/local_parametrization_wrapper.h +++ b/src/ceres_wrapper/local_parametrization_wrapper.h @@ -21,7 +21,7 @@ class LocalParametrizationWrapper : public ceres::LocalParameterization LocalParametrizationWrapper(LocalParametrizationBasePtr _local_parametrization_ptr); - virtual ~LocalParametrizationWrapper(); + virtual ~LocalParametrizationWrapper() = default; virtual bool Plus(const double* x_raw, const double* delta_raw, double* x_plus_delta_raw) const; @@ -32,6 +32,8 @@ class LocalParametrizationWrapper : public ceres::LocalParameterization virtual int LocalSize() const; }; +using LocalParametrizationWrapperPtr = std::shared_ptr<LocalParametrizationWrapper>; + } // namespace wolf #include "../local_parametrization_base.h" @@ -43,10 +45,6 @@ inline LocalParametrizationWrapper::LocalParametrizationWrapper(LocalParametriza { } -inline LocalParametrizationWrapper::~LocalParametrizationWrapper() -{ -} - inline int LocalParametrizationWrapper::GlobalSize() const { return local_parametrization_ptr_->getGlobalSize(); diff --git a/src/constraint_AHP.h b/src/constraint_AHP.h index 73c84a9570db2bf4a7b2a5fe7e0742801f05006c..e7acfc0a354713bc2f408effb4907f6576a15d58 100644 --- a/src/constraint_AHP.h +++ b/src/constraint_AHP.h @@ -92,14 +92,15 @@ inline Eigen::VectorXs ConstraintAHP::expectation() const FrameBasePtr frm_anchor = getFrameOtherPtr(); LandmarkBasePtr lmk = getLandmarkOtherPtr(); - const Scalar* const frame_current_pos = frm_current->getPPtr()->getPtr(); - const Scalar* const frame_current_ori = frm_current->getOPtr()->getPtr(); - const Scalar* const frame_anchor_pos = frm_anchor ->getPPtr()->getPtr(); - const Scalar* const frame_anchor_ori = frm_anchor ->getOPtr()->getPtr(); - const Scalar* const lmk_pos_hmg = lmk ->getPPtr()->getPtr(); + const Eigen::MatrixXs frame_current_pos = frm_current->getPPtr()->getState(); + const Eigen::MatrixXs frame_current_ori = frm_current->getOPtr()->getState(); + const Eigen::MatrixXs frame_anchor_pos = frm_anchor ->getPPtr()->getState(); + const Eigen::MatrixXs frame_anchor_ori = frm_anchor ->getOPtr()->getState(); + const Eigen::MatrixXs lmk_pos_hmg = lmk ->getPPtr()->getState(); Eigen::Vector2s exp; - expectation(frame_current_pos, frame_current_ori, frame_anchor_pos, frame_anchor_ori, lmk_pos_hmg, exp.data()); + expectation(frame_current_pos.data(), frame_current_ori.data(), frame_anchor_pos.data(), + frame_anchor_ori.data(), lmk_pos_hmg.data(), exp.data()); return exp; } @@ -138,7 +139,7 @@ inline void ConstraintAHP::expectation(const T* const _current_frame_p, // current robot to current camera transform CaptureBasePtr current_capture = this->getFeaturePtr()->getCapturePtr(); Translation<T, 3> t_r1_c1 (current_capture->getSensorPPtr()->getState().cast<T>()); - Quaternions q_r1_c1_s(current_capture->getSensorOPtr()->getPtr()); + Quaternions q_r1_c1_s(Eigen::Vector4s(current_capture->getSensorOPtr()->getState())); Quaternion<T> q_r1_c1 = q_r1_c1_s.cast<T>(); TransformType T_R1_C1 = t_r1_c1 * q_r1_c1; diff --git a/src/constraint_analytic.cpp b/src/constraint_analytic.cpp index c2b0268e3f819162050a7404346a9a70ce388642..8b0422380bc4ad0d39f2e7f38955ea3b0bd948a8 100644 --- a/src/constraint_analytic.cpp +++ b/src/constraint_analytic.cpp @@ -29,20 +29,18 @@ ConstraintAnalytic::ConstraintAnalytic(const std::string& _tp, { resizeVectors(); } - - -std::vector<Scalar*> ConstraintAnalytic::getStateScalarPtrVector() const +/* +ConstraintAnalytic::ConstraintAnalytic(ConstraintType _tp, const LandmarkBasePtr& _landmark_ptr, const ProcessorBasePtr& _processor_ptr, + bool _apply_loss_function, ConstraintStatus _status, + StateBlockPtr _state0Ptr, StateBlockPtr _state1Ptr, StateBlockPtr _state2Ptr, StateBlockPtr _state3Ptr, StateBlockPtr _state4Ptr, + StateBlockPtr _state5Ptr, StateBlockPtr _state6Ptr, StateBlockPtr _state7Ptr, StateBlockPtr _state8Ptr, StateBlockPtr _state9Ptr ) : + ConstraintBase( _tp, nullptr, nullptr, _landmark_ptr, _processor_ptr, _apply_loss_function, _status), + state_ptr_vector_({_state0Ptr, _state1Ptr, _state2Ptr, _state3Ptr, _state4Ptr, + _state5Ptr, _state6Ptr, _state7Ptr, _state8Ptr, _state9Ptr}) { - assert(state_ptr_vector_.size() > 0 && state_ptr_vector_.size() <= 10 && "Wrong state vector size in constraint, it should be between 1 and 10"); - - std::vector<Scalar*> state_scalar_ptr_vector(state_ptr_vector_.size()); - - for (auto i = 0; i < state_scalar_ptr_vector.size(); i++) - state_scalar_ptr_vector[i] = state_ptr_vector_[i]->getPtr(); - - return state_scalar_ptr_vector; + resizeVectors(); } - +*/ std::vector<StateBlockPtr> ConstraintAnalytic::getStateBlockPtrVector() const { return state_ptr_vector_; diff --git a/src/constraint_analytic.h b/src/constraint_analytic.h index 9384afd71f23b46773dc59d1166830ce6a6d0272..5fb1495bfbb8963c8e1f0252aaac1a75719821d8 100644 --- a/src/constraint_analytic.h +++ b/src/constraint_analytic.h @@ -60,13 +60,6 @@ class ConstraintAnalytic: public ConstraintBase virtual ~ConstraintAnalytic() = default; - /** \brief Returns a vector of pointers to the state blocks - * - * Returns a vector of pointers to the state blocks in which this constraint depends - * - **/ - virtual std::vector<Scalar*> getStateScalarPtrVector() const override; - /** \brief Returns a vector of pointers to the states * * Returns a vector of pointers to the state in which this constraint depends diff --git a/src/constraint_autodiff.h b/src/constraint_autodiff.h index 7e6f227a44da539cb80a2d4a97f1e114372b93c5..09472aa90b31d8b1f000b6db7de1aaa65fcd442f 100644 --- a/src/constraint_autodiff.h +++ b/src/constraint_autodiff.h @@ -270,26 +270,6 @@ class ConstraintAutodiff : public ConstraintBase // std::cout << jacobians_[i] << std::endl << std::endl; } - /** \brief Returns a vector of pointers to the state blocks - * - * Returns a vector of pointers to the state blocks in which this constraint depends - * - **/ - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - state_ptrs_[5]->getPtr(), - state_ptrs_[6]->getPtr(), - state_ptrs_[7]->getPtr(), - state_ptrs_[8]->getPtr(), - state_ptrs_[9]->getPtr() - }); - } - /** \brief Returns a vector of pointers to the states * * Returns a vector of pointers to the state in which this constraint depends @@ -556,20 +536,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,B4,B5,B6,B7,B8,0> : public Constra // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - state_ptrs_[5]->getPtr(), - state_ptrs_[6]->getPtr(), - state_ptrs_[7]->getPtr(), - state_ptrs_[8]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -811,19 +777,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,B4,B5,B6,B7,0,0> : public Constrai // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - state_ptrs_[5]->getPtr(), - state_ptrs_[6]->getPtr(), - state_ptrs_[7]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -1054,18 +1007,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,B4,B5,B6,0,0,0> : public Constrain // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - state_ptrs_[5]->getPtr(), - state_ptrs_[6]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -1281,17 +1222,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,B4,B5,0,0,0,0> : public Constraint jacobians_[i].data() + row * state_block_sizes_.at(i)); } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - state_ptrs_[5]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -1495,16 +1425,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,B4,0,0,0,0,0> : public ConstraintB jacobians_[i].data() + row * state_block_sizes_.at(i)); } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr(), - state_ptrs_[4]->getPtr(), - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -1701,15 +1621,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,B3,0,0,0,0,0,0> : public ConstraintBa // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr(), - state_ptrs_[3]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -1895,14 +1806,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,B2,0,0,0,0,0,0,0> : public ConstraintBas // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr(), - state_ptrs_[2]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -2077,13 +1980,6 @@ class ConstraintAutodiff<CtrT,RES,B0,B1,0,0,0,0,0,0,0,0> : public ConstraintBase // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr(), - state_ptrs_[1]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; @@ -2247,12 +2143,6 @@ class ConstraintAutodiff<CtrT,RES,B0,0,0,0,0,0,0,0,0,0> : public ConstraintBase // std::cout << jacobians_[i] << std::endl << std::endl; } - virtual std::vector<Scalar*> getStateScalarPtrVector() const - { - return std::vector<Scalar*>({state_ptrs_[0]->getPtr() - }); - } - virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const { return state_ptrs_; diff --git a/src/constraint_base.h b/src/constraint_base.h index c5b2a756480a8f2a75ac3c55fcb49971d3a4ae9b..c90ade9153062c8e871ef450452208c50a8dcf72 100644 --- a/src/constraint_base.h +++ b/src/constraint_base.h @@ -91,10 +91,6 @@ class ConstraintBase : public NodeBase, public std::enable_shared_from_this<Cons **/ virtual JacobianMethod getJacobianMethod() const = 0; - /** \brief Returns a vector of scalar pointers to the first element of all state blocks involved in the constraint - **/ - virtual std::vector<Scalar*> getStateScalarPtrVector() const = 0; - /** \brief Returns a vector of pointers to the states in which this constraint depends **/ virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const = 0; diff --git a/src/constraint_epipolar.h b/src/constraint_epipolar.h index 2d7d2a14214be26a6ee19fd858c86a72ea269a6e..262b3bc7858922e57e2e4f14cc453d6ad3c86fde 100644 --- a/src/constraint_epipolar.h +++ b/src/constraint_epipolar.h @@ -32,10 +32,6 @@ class ConstraintEpipolar : public ConstraintBase **/ virtual JacobianMethod getJacobianMethod() const override {return JAC_ANALYTIC;} - /** \brief Returns a vector of scalar pointers to the first element of all state blocks involved in the constraint - **/ - virtual std::vector<Scalar*> getStateScalarPtrVector() const override {return std::vector<Scalar*>(0);} - /** \brief Returns a vector of pointers to the states in which this constraint depends **/ virtual std::vector<StateBlockPtr> getStateBlockPtrVector() const override {return std::vector<StateBlockPtr>(0);} diff --git a/src/constraint_odom_3D.h b/src/constraint_odom_3D.h index a3d4b7af0ae3419d0a198591750aa174aeb26769..26811e4707fcc90f85a230a98903d3f77c6150cf 100644 --- a/src/constraint_odom_3D.h +++ b/src/constraint_odom_3D.h @@ -111,18 +111,32 @@ inline bool ConstraintOdom3D::expectation(const T* const _p_current, const T* co Eigen::Map<Eigen::Matrix<T,3,1> > expectation_dp(_expectation_dp); Eigen::Map<Eigen::Quaternion<T> > expectation_dq(_expectation_dq); - -// std::cout << "p_current: " << p_current(0) << std::endl << p_current(1) << std::endl << p_current(2) << std::endl; -// std::cout << "q_current: " << q_current.x() << std::endl << q_current.y() << std::endl << q_current.z() << std::endl << q_current.w() << std::endl; -// std::cout << "p_past: " << p_past(0) << std::endl << p_past(1) << std::endl << p_past(2) << std::endl; -// std::cout << "q_past: " << q_past.x() << std::endl << q_past.y() << std::endl << q_past.z() << std::endl << q_past.w() << std::endl; +// std::cout << "p_current: " << p_current(0) << " " +// << p_current(1) << " " +// << p_current(2) << "\n"; +// std::cout << "q_current: " << q_current.coeffs()(0) << " " +// << q_current.coeffs()(1) << " " +// << q_current.coeffs()(2) << " " +// << q_current.coeffs()(3) << "\n"; +// std::cout << "p_past: " << p_past(0) << " " +// << p_past(1) << " " +// << p_past(2) << "\n"; +// std::cout << "q_past: " << q_past.coeffs()(0) << " " +// << q_past.coeffs()(1) << " " +// << q_past.coeffs()(2) << " " +// << q_past.coeffs()(3) << "\n"; // estimate motion increment, dp, dq; expectation_dp = q_past.conjugate() * (p_current - p_past); - expectation_dq = q_past.conjugate() * q_current; + expectation_dq = q_past.conjugate() * q_current; -// std::cout << "exp_p: " << expectation_dp(0) << std::endl << expectation_dp(1) << std::endl << expectation_dp(2) << std::endl; -// std::cout << "exp_q: " << expectation(3) << std::endl << expectation(4) << std::endl << expectation(5) << std::endl << expectation(6) << std::endl; +// std::cout << "exp_p: " << expectation_dp(0) << " " +// << expectation_dp(1) << " " +// << expectation_dp(2) << "\n"; +// std::cout << "exp_q: " << expectation_dq.coeffs()(0) << " " +// << expectation_dq.coeffs()(1) << " " +// << expectation_dq.coeffs()(2) << " " +// << expectation_dq.coeffs()(3) << "\n"; return true; } @@ -132,18 +146,18 @@ inline Eigen::VectorXs ConstraintOdom3D::expectation() const Eigen::VectorXs exp(7); FrameBasePtr frm_current = getFeaturePtr()->getFramePtr(); FrameBasePtr frm_past = getFrameOtherPtr(); - const Scalar * const frame_current_pos = frm_current->getPPtr()->getState().data(); - const Scalar * const frame_current_ori = frm_current->getOPtr()->getState().data(); - const Scalar * const frame_past_pos = frm_past->getPPtr()->getState().data(); - const Scalar * const frame_past_ori = frm_past->getOPtr()->getState().data(); - -// std::cout << "frame_current_pos: " << frm_current->getPPtr()->getVector().transpose() << std::endl; -// std::cout << "frame_past_pos: " << frm_past->getPPtr()->getVector().transpose() << std::endl; - - expectation(frame_current_pos, - frame_current_ori, - frame_past_pos, - frame_past_ori, + const Eigen::VectorXs frame_current_pos = frm_current->getPPtr()->getState(); + const Eigen::VectorXs frame_current_ori = frm_current->getOPtr()->getState(); + const Eigen::VectorXs frame_past_pos = frm_past->getPPtr()->getState(); + const Eigen::VectorXs frame_past_ori = frm_past->getOPtr()->getState(); + +// std::cout << "frame_current_pos: " << frm_current->getPPtr()->getState().transpose() << std::endl; +// std::cout << "frame_past_pos: " << frm_past->getPPtr()->getState().transpose() << std::endl; + + expectation(frame_current_pos.data(), + frame_current_ori.data(), + frame_past_pos.data(), + frame_past_ori.data(), exp.data(), exp.data()+3); return exp; diff --git a/src/examples/test_imuDock.cpp b/src/examples/test_imuDock.cpp index 903e5c5201658143e776ba998180f7e5aaaffd2e..d68e8dd4391d9733c81c55c8f78d821f140fe700 100644 --- a/src/examples/test_imuDock.cpp +++ b/src/examples/test_imuDock.cpp @@ -240,8 +240,8 @@ int main(int argc, char** argv) // ___Solve + compute covariances___ problem->print(4,0,1,0); - std::string report = ceres_manager->solve(1); // 0: nothing, 1: BriefReport, 2: FullReport - ceres_manager->computeCovariances(ALL_MARGINALS); + std::string report = ceres_manager->solve(SolverManager::ReportVerbosity::BRIEF); // 0: nothing, 1: BriefReport, 2: FullReport + ceres_manager->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); problem->print(1,0,1,0); //#################################################### RESULTS PART diff --git a/src/examples/test_imuDock_autoKFs.cpp b/src/examples/test_imuDock_autoKFs.cpp index 53f2fd9bdc893a90698293d383760ac9b5c9621d..03677027f7dc687d4e55a303ccbbefe2030a4c3a 100644 --- a/src/examples/test_imuDock_autoKFs.cpp +++ b/src/examples/test_imuDock_autoKFs.cpp @@ -249,8 +249,8 @@ int main(int argc, char** argv) // ___Solve + compute covariances___ problem->print(4,0,1,0); - std::string report = ceres_manager->solve(1);// 0: nothing, 1: BriefReport, 2: FullReport - ceres_manager->computeCovariances(ALL_MARGINALS); + std::string report = ceres_manager->solve(SolverManager::ReportVerbosity::BRIEF); + ceres_manager->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); problem->print(1,0,1,0); //#################################################### RESULTS PART diff --git a/src/examples/test_imuPlateform_Offline.cpp b/src/examples/test_imuPlateform_Offline.cpp index 644bf155a9d0efc19b7e2221933253a1feafd278..9d834d73e8408b1207a8f48d9225b4ec2f08d989 100644 --- a/src/examples/test_imuPlateform_Offline.cpp +++ b/src/examples/test_imuPlateform_Offline.cpp @@ -201,9 +201,9 @@ int main(int argc, char** argv) origin_KF->getVPtr()->fix(); std::cout << "\t\t\t ______solving______" << std::endl; - std::string report = ceres_manager_wolf_diff->solve(2);// 0: nothing, 1: BriefReport, 2: FullReport + std::string report = ceres_manager_wolf_diff->solve(SolverManager::ReportVerbosity::FULL);// 0: nothing, 1: BriefReport, 2: FullReport std::cout << report << std::endl; - ceres_manager_wolf_diff->computeCovariances(ALL); + ceres_manager_wolf_diff->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL); std::cout << "\t\t\t ______solved______" << std::endl; wolf_problem_ptr_->print(4,1,1,1); diff --git a/src/examples/test_imu_constrained0.cpp b/src/examples/test_imu_constrained0.cpp index 2ee096b4e26cbab0aaa44ff31ec9f7ed972ae4a6..87330497c75beb1e0464382fd4ec1437bc848272 100644 --- a/src/examples/test_imu_constrained0.cpp +++ b/src/examples/test_imu_constrained0.cpp @@ -259,16 +259,16 @@ int main(int argc, char** argv) std::cout << "\t\t\t ______solving______" << std::endl; - std::string report = ceres_manager_wolf_diff->solve(2); //0: nothing, 1: BriefReport, 2: FullReport + std::string report = ceres_manager_wolf_diff->solve(SolverManager::ReportVerbosity::FULL); //0: nothing, 1: BriefReport, 2: FullReport std::cout << report << std::endl; last_KF->getAccBiasPtr()->fix(); last_KF->getGyroBiasPtr()->fix(); std::cout << "\t\t\t solving after fixBias" << std::endl; - report = ceres_manager_wolf_diff->solve(1); //0: nothing, 1: BriefReport, 2: FullReport + report = ceres_manager_wolf_diff->solve(SolverManager::ReportVerbosity::BRIEF); //0: nothing, 1: BriefReport, 2: FullReport std::cout << report << std::endl; - ceres_manager_wolf_diff->computeCovariances(ALL); + ceres_manager_wolf_diff->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL); std::cout << "\t\t\t ______solved______" << std::endl; wolf_problem_ptr_->print(4,1,1,1); diff --git a/src/examples/test_processor_odom_3D.cpp b/src/examples/test_processor_odom_3D.cpp index 6cb5e458dd92f40abfb37d26aa601c0242c8f510..8cfdb9d8822347057fe30751058f253b5ea340b9 100644 --- a/src/examples/test_processor_odom_3D.cpp +++ b/src/examples/test_processor_odom_3D.cpp @@ -93,7 +93,7 @@ int main (int argc, char** argv) // frm->setState(problem->zeroState()); // } // problem->print(1,0,1,0); - std::string brief_report = ceres_manager.solve(1);// 0, 1 or 2 + std::string brief_report = ceres_manager.solve(SolverManager::ReportVerbosity::FULL); std::cout << brief_report << std::endl; problem->print(1,0,1,0); diff --git a/src/examples/test_processor_tracker_landmark_image.cpp b/src/examples/test_processor_tracker_landmark_image.cpp index b9ea3772d7d93882e475263e48903a3d884ed1a2..4060656a2ac762d4bb2ac4904f047cf9ccccd163 100644 --- a/src/examples/test_processor_tracker_landmark_image.cpp +++ b/src/examples/test_processor_tracker_landmark_image.cpp @@ -229,7 +229,7 @@ int main(int argc, char** argv) if (problem->getTrajectoryPtr()->getFrameList().size() > number_of_KFs) { number_of_KFs = problem->getTrajectoryPtr()->getFrameList().size(); - std::string summary = ceres_manager.solve(1);// 0: nothing, 1: BriefReport, 2: FullReport + std::string summary = ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF);// 0: nothing, 1: BriefReport, 2: FullReport std::cout << summary << std::endl; } diff --git a/src/examples/test_simple_AHP.cpp b/src/examples/test_simple_AHP.cpp index bc2d27c54fff6bf8aede8e0d127664bde1a662b5..0f4d3f8eb8d7af228db27d3535c808909a780356 100644 --- a/src/examples/test_simple_AHP.cpp +++ b/src/examples/test_simple_AHP.cpp @@ -242,7 +242,7 @@ int main(int argc, char** argv) CeresManager ceres_manager(problem, ceres_options); - std::string summary = ceres_manager.solve(2);// 0: nothing, 1: BriefReport, 2: FullReport + std::string summary = ceres_manager.solve(SolverManager::ReportVerbosity::FULL);// 0: nothing, 1: BriefReport, 2: FullReport std::cout << summary << std::endl; // Test of convergence over the lmk params diff --git a/src/examples/test_sparsification.cpp b/src/examples/test_sparsification.cpp index bf797869098964ffe95683a7155e8657d6622b4f..ea8113d1bccfc185a9ea69fedbd90f0967969922 100644 --- a/src/examples/test_sparsification.cpp +++ b/src/examples/test_sparsification.cpp @@ -291,11 +291,11 @@ int main(int argc, char** argv) // SOLVE // solution - bl_summary = bl_ceres_manager->solve(1); + bl_summary = bl_ceres_manager->solve(SolverManager::ReportVerbosity::FULL); std::cout << bl_summary << std::endl; // covariance - bl_ceres_manager->computeCovariances(ALL);//ALL_MARGINALS + bl_ceres_manager->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL);//ALL_MARGINALS // t1 = clock(); diff --git a/src/hello_wolf/hello_wolf.cpp b/src/hello_wolf/hello_wolf.cpp index 27eb81987b9918e570c7a94420581f18b87b1651..653fdcc9ebd696d9774a97a60cb66d0016500227 100644 --- a/src/hello_wolf/hello_wolf.cpp +++ b/src/hello_wolf/hello_wolf.cpp @@ -214,7 +214,7 @@ int main() // SOLVE with exact initial guess WOLF_TRACE("======== SOLVE PROBLEM WITH EXACT PRIORS =======") - std::string report = ceres->solve(2); + std::string report = ceres->solve(wolf::SolverManager::ReportVerbosity::FULL); WOLF_TRACE(report); // should show a very low iteration number (possibly 1) problem->print(4,1,1,1); @@ -232,13 +232,13 @@ int main() // SOLVE again WOLF_TRACE("======== SOLVE PROBLEM WITH PERTURBED PRIORS =======") - report = ceres->solve(2); + report = ceres->solve(wolf::SolverManager::ReportVerbosity::FULL); WOLF_TRACE(report); // should show a very high iteration number (more than 10, or than 100!) problem->print(4,1,1,1); // GET COVARIANCES of all states WOLF_TRACE("======== COVARIANCES OF SOLVED PROBLEM =======") - ceres->computeCovariances(ALL_MARGINALS); + ceres->computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); for (auto kf : problem->getTrajectoryPtr()->getFrameList()) if (kf->isKey()) WOLF_TRACE("KF", kf->id(), "_cov = \n", kf->getCovariance()); diff --git a/src/landmark_container.cpp b/src/landmark_container.cpp index 0979387a6139c7afb2393d713da2722f04559385..a1ef7ed100e31b72619507bcb4d0663e1d50fe0c 100644 --- a/src/landmark_container.cpp +++ b/src/landmark_container.cpp @@ -30,16 +30,17 @@ LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, M_PI / 4, 3 * M_PI / 4,-3 * M_PI / 4,-M_PI / 4; // Computing center - std::cout << "Container constructor: Computing center pose... " << std::endl; - Eigen::Map<Eigen::Vector2s> container_position(getPPtr()->getPtr()); - Eigen::Map<Eigen::Vector1s> container_orientation(getOPtr()->getPtr()); + WOLF_DEBUG( "Container constructor: Computing center pose... " ); + Eigen::Vector2s container_position(getPPtr()->getState()); + Eigen::Vector1s container_orientation(getOPtr()->getState()); - std::cout << "Container constructor: _corner_1_idx " << _corner_1_idx << "_corner_2_idx " << _corner_2_idx << std::endl; + WOLF_DEBUG( "Container constructor: _corner_1_idx ", _corner_1_idx, + "_corner_2_idx ", _corner_2_idx ); // Large side detected (A & B) if ( (_corner_1_idx == 0 && _corner_2_idx == 1) || (_corner_1_idx == 1 && _corner_2_idx == 0) ) { - std::cout << "Large side detected" << std::endl; + WOLF_DEBUG( "Large side detected" ); Eigen::Vector2s AB = (_corner_1_idx == 0 ? _corner_2_pose.head(2) - _corner_1_pose.head(2) : _corner_1_pose.head(2) - _corner_2_pose.head(2)); Eigen::Vector2s perpendicularAB; perpendicularAB << -AB(1)/AB.norm(), AB(0)/AB.norm(); @@ -50,7 +51,7 @@ LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, // Short side detected (B & C) else if ( (_corner_1_idx == 1 && _corner_2_idx == 2) || (_corner_1_idx == 2 && _corner_2_idx == 1) ) { - std::cout << "Short side detected" << std::endl; + WOLF_DEBUG( "Short side detected" ); Eigen::Vector2s BC = (_corner_1_idx == 1 ? _corner_2_pose.head(2) - _corner_1_pose.head(2) : _corner_1_pose.head(2) - _corner_2_pose.head(2)); Eigen::Vector2s perpendicularBC; perpendicularBC << -BC(1)/BC.norm(), BC(0)/BC.norm(); @@ -62,7 +63,7 @@ LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, // A & C else if ( (_corner_1_idx == 0 && _corner_2_idx == 2) || (_corner_1_idx == 2 && _corner_2_idx == 0) ) { - std::cout << "diagonal AC detected" << std::endl; + WOLF_DEBUG( "diagonal AC detected" ); Eigen::Vector2s AC = (_corner_1_idx == 0 ? _corner_2_pose.head(2) - _corner_1_pose.head(2) : _corner_1_pose.head(2) - _corner_2_pose.head(2)); container_position = (_corner_1_idx == 0 ? _corner_1_pose.head(2) : _corner_2_pose.head(2)) + AC / 2; container_orientation(0) = atan2(AC(1),AC(0)) - atan2(_witdh,_length); @@ -70,7 +71,7 @@ LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, // B & D else if ( (_corner_1_idx == 1 && _corner_2_idx == 3) || (_corner_1_idx == 3 && _corner_2_idx == 1) ) { - std::cout << "diagonal BD detected" << std::endl; + WOLF_DEBUG( "diagonal BD detected" ); Eigen::Vector2s BD = (_corner_1_idx == 1 ? _corner_2_pose.head(2) - _corner_1_pose.head(2) : _corner_1_pose.head(2) - _corner_2_pose.head(2)); container_position = (_corner_1_idx == 1 ? _corner_1_pose.head(2) : _corner_2_pose.head(2)) + BD / 2; container_orientation(0) = atan2(BD(1),BD(0)) + atan2(_witdh,_length); @@ -78,9 +79,12 @@ LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, else assert(0 && "index corners combination not implemented!"); - std::cout << "_corner_1_pose... " << _corner_1_pose.transpose() << std::endl; - std::cout << "_corner_2_pose... " << _corner_2_pose.transpose() << std::endl; - std::cout << "Container center pose... " << container_position.transpose() << " " << container_orientation.transpose() << std::endl; + WOLF_DEBUG( "_corner_1_pose... ", _corner_1_pose.transpose() ); + WOLF_DEBUG( "_corner_2_pose... ", _corner_2_pose.transpose() ); + WOLF_DEBUG( "Container center pose... ", container_position.transpose(), " ", container_orientation.transpose() ); + + getPPtr()->setState(container_position); + getOPtr()->setState(container_orientation); } //LandmarkContainer::LandmarkContainer(StateBlockPtr _p_ptr, StateBlockPtr _o_ptr, LandmarkCorner2D* _corner_A_ptr, LandmarkCorner2D* _corner_B_ptr, LandmarkCorner2D* _corner_C_ptr, LandmarkCorner2D* _corner_D_ptr, const Scalar& _witdh, const Scalar& _length) : diff --git a/src/landmark_polyline_2D.cpp b/src/landmark_polyline_2D.cpp index bc1bcc71abedb342e2003498844593db8e538b36..d117754206d53c9a409e5e04e6e92548a0249d12 100644 --- a/src/landmark_polyline_2D.cpp +++ b/src/landmark_polyline_2D.cpp @@ -60,7 +60,7 @@ void LandmarkPolyline2D::setLast(const Eigen::VectorXs& _point, bool _defined) defineExtreme(true); } -const Eigen::VectorXs& LandmarkPolyline2D::getPointVector(int _i) const +const Eigen::VectorXs LandmarkPolyline2D::getPointVector(int _i) const { //std::cout << "LandmarkPolyline2D::getPointVector: " << _i << std::endl; //std::cout << "First: " << first_id_ << " - size: " << point_state_ptr_vector_.size() << std::endl; diff --git a/src/landmark_polyline_2D.h b/src/landmark_polyline_2D.h index d2b8fb8f93e92896f85bcdd30b641346a9d1a754..a44a00b4cf5cf3aef2c560693e3232560e01a63a 100644 --- a/src/landmark_polyline_2D.h +++ b/src/landmark_polyline_2D.h @@ -72,7 +72,7 @@ class LandmarkPolyline2D : public LandmarkBase int getFirstId() const; int getLastId() const; - const Eigen::VectorXs& getPointVector(int _i) const; + const Eigen::VectorXs getPointVector(int _i) const; StateBlockPtr getPointStateBlockPtr(int _i); diff --git a/src/make_unique.h b/src/make_unique.h new file mode 100644 index 0000000000000000000000000000000000000000..f336eb4f7ff52eae0e7014505180bb060f48ee70 --- /dev/null +++ b/src/make_unique.h @@ -0,0 +1,24 @@ +/** + * \file make_unique.h + * + * Created on: Oct 11, 2017 + * \author: Jeremie Deray + */ + +#ifndef _WOLF_MAKE_UNIQUE_H_ +#define _WOLF_MAKE_UNIQUE_H_ + +#include <memory> + +namespace wolf { + +/// @note this appears only in cpp14 +template <typename T, typename... Args> +std::unique_ptr<T> make_unique(Args&&... args) +{ + return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); +} + +} + +#endif /* _WOLF_MAKE_UNIQUE_H_ */ diff --git a/src/problem.cpp b/src/problem.cpp index 50100be20ff50ec47858026cbbf5ec44f1bb20ad..2bf9ad01fa944fe8ae57dad5a325c550dff4285d 100644 --- a/src/problem.cpp +++ b/src/problem.cpp @@ -371,8 +371,13 @@ StateBlockPtr Problem::addStateBlock(StateBlockPtr _state_ptr) // add the state unit to the list state_block_list_.push_back(_state_ptr); + // queue for solver manager - state_block_notification_list_.push_back(StateBlockNotification({ADD,_state_ptr})); + _state_ptr->addNotification(StateBlock::Notification::ADD); + notified_state_block_list_.push_back(_state_ptr); + notified_state_block_list_.sort(); + notified_state_block_list_.unique(); + return _state_ptr; } @@ -381,7 +386,10 @@ void Problem::updateStateBlockPtr(StateBlockPtr _state_ptr) //std::cout << "Problem::updateStateBlockPtr " << _state_ptr.get() << std::endl; // queue for solver manager - state_block_notification_list_.push_back(StateBlockNotification({UPDATE,_state_ptr})); + _state_ptr->addNotification(StateBlock::Notification::FIX_UPDATE); + notified_state_block_list_.push_back(_state_ptr); + notified_state_block_list_.sort(); + notified_state_block_list_.unique(); } void Problem::removeStateBlockPtr(StateBlockPtr _state_ptr) @@ -391,19 +399,11 @@ void Problem::removeStateBlockPtr(StateBlockPtr _state_ptr) // add the state unit to the list state_block_list_.remove(_state_ptr); - // Check if the state addition is still as a notification - auto state_notif_it = state_block_notification_list_.begin(); - for (; state_notif_it != state_block_notification_list_.end(); state_notif_it++) - if (state_notif_it->notification_ == ADD && state_notif_it->state_block_ptr_ == _state_ptr) - break; - - // Remove addition notification - if (state_notif_it != state_block_notification_list_.end()) - state_block_notification_list_.erase(state_notif_it); // Add remove notification - else - state_block_notification_list_.push_back(StateBlockNotification({REMOVE, _state_ptr})); - + _state_ptr->addNotification(StateBlock::Notification::REMOVE); + notified_state_block_list_.push_back(_state_ptr); + notified_state_block_list_.sort(); + notified_state_block_list_.unique(); } ConstraintBasePtr Problem::addConstraintPtr(ConstraintBasePtr _constraint_ptr) diff --git a/src/problem.h b/src/problem.h index 53ee4c59b9b4be14213d3a2a3f75ee51ae29cb9e..ac69bd6c37a5d18401344bdc973bc827ae51f72b 100644 --- a/src/problem.h +++ b/src/problem.h @@ -29,11 +29,7 @@ enum Notification REMOVE, UPDATE }; -struct StateBlockNotification -{ - Notification notification_; - StateBlockPtr state_block_ptr_; -}; + struct ConstraintNotification { Notification notification_; @@ -53,10 +49,10 @@ class Problem : public std::enable_shared_from_this<Problem> ProcessorMotionPtr processor_motion_ptr_; StateBlockList state_block_list_; std::map<std::pair<StateBlockPtr, StateBlockPtr>, Eigen::MatrixXs> covariances_; - std::list<StateBlockNotification> state_block_notification_list_; std::list<ConstraintNotification> constraint_notification_list_; bool prior_is_set_; Size state_size_, state_cov_size_; + StateBlockList notified_state_block_list_; private: // CAUTION: THESE METHODS ARE PRIVATE, DO NOT MAKE THEM PUBLIC !! Problem(const std::string& _frame_structure); // USE create() below !! @@ -278,10 +274,9 @@ class Problem : public std::enable_shared_from_this<Problem> */ void removeStateBlockPtr(StateBlockPtr _state_ptr); - /** \brief Gets a queue of state blocks notification to be handled by the solver + /** \brief Gets a list of state blocks which state has been changed to be handled by the solver */ - std::list<StateBlockNotification>& getStateBlockNotificationList(); - + StateBlockList& getNotifiedStateBlockList(); /** \brief Gets a queue of constraint notification to be handled by the solver */ @@ -331,16 +326,15 @@ inline ProcessorMotionPtr& Problem::getProcessorMotionPtr() return processor_motion_ptr_; } -inline std::list<StateBlockNotification>& Problem::getStateBlockNotificationList() -{ - return state_block_notification_list_; -} - inline std::list<ConstraintNotification>& Problem::getConstraintNotificationList() { return constraint_notification_list_; } +inline StateBlockList& Problem::getNotifiedStateBlockList() +{ + return notified_state_block_list_; +} } // namespace wolf diff --git a/src/processor_base.h b/src/processor_base.h index 73fdc721ebbadc8630f36772282c44db9b45afd6..d63edd93cdf79cb5381531f669fc6e5635bcfb39 100644 --- a/src/processor_base.h +++ b/src/processor_base.h @@ -109,10 +109,31 @@ class KFPackBuffer */ struct ProcessorParamsBase { + ProcessorParamsBase() = default; + + ProcessorParamsBase(bool _voting_active, + Scalar _time_tolerance, + const std::string& _type, + const std::string& _name) + : voting_active(_voting_active) + , time_tolerance(_time_tolerance) + , type(_type) + , name(_name) + { + // + } + + virtual ~ProcessorParamsBase() = default; + + bool voting_active = false; + + ///< maximum time difference between a Keyframe time stamp and + /// a particular Capture of this processor to allow assigning + /// this Capture to the Keyframe. + Scalar time_tolerance = Scalar(0); + std::string type; std::string name; - Scalar time_tolerance; ///< maximum time difference between a Keyframe time stamp and a particular Capture of this processor to allow assigning this Capture to the Keyframe. - bool voting_active; }; //class ProcessorBase diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index 60df425ecf4f7c061b022515ffa4456b457604e7..7263fb5e8ffab31a2b7dce2857fc840f2604b2b7 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -1,12 +1,9 @@ -SET(HDRS_SOLVER - ccolamd_ordering.h - cost_function_base.h - cost_function_sparse_base.h - cost_function_sparse.h - qr_solver.h - solver_manager.h - solver_QR.h - sparse_utils.h) -SET(SRCS_SOLVER - solver_manager.cpp - ) \ No newline at end of file +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) + +# Forward var to parent scope + +SET(HDRS_SOLVER ${HDRS_SOLVER} + ${CMAKE_CURRENT_SOURCE_DIR}/solver_manager.h PARENT_SCOPE) + +SET(SRCS_SOLVER ${SRCS_SOLVER} + ${CMAKE_CURRENT_SOURCE_DIR}/solver_manager.cpp PARENT_SCOPE) diff --git a/src/solver/solver_manager.cpp b/src/solver/solver_manager.cpp index cb39335b0705f8edf6222d78db36a0e18c21d504..b26b977a519983f5d0e06b6cd177682dd78272a4 100644 --- a/src/solver/solver_manager.cpp +++ b/src/solver/solver_manager.cpp @@ -1,245 +1,181 @@ -#include "ceres_manager.h" +#include "solver_manager.h" +#include "../trajectory_base.h" +#include "../map_base.h" +#include "../landmark_base.h" -SolverManager::SolverManager() -{ - -} +namespace wolf { -SolverManager::~SolverManager() +SolverManager::SolverManager(const ProblemPtr& _wolf_problem) : + wolf_problem_(_wolf_problem) { - removeAllStateUnits(); + assert(_wolf_problem != nullptr && "Passed a nullptr ProblemPtr."); } -void SolverManager::solve() +void SolverManager::update() { - + // REMOVE CONSTRAINTS + auto ctr_notification_it = wolf_problem_->getConstraintNotificationList().begin(); + while ( ctr_notification_it != wolf_problem_->getConstraintNotificationList().end() ) + { + if (ctr_notification_it->notification_ == REMOVE) + { + removeConstraint(ctr_notification_it->constraint_ptr_); + ctr_notification_it = wolf_problem_->getConstraintNotificationList().erase(ctr_notification_it); + } + else + ctr_notification_it++; + } + + StateBlockList& states = wolf_problem_->getNotifiedStateBlockList(); + + for (StateBlockPtr& state : states) + { + const auto notifications = state->consumeNotifications(); + + for (const auto notif : notifications) + { + switch (notif) + { + case StateBlock::Notification::ADD: + { + const bool registered = state_blocks_.find(state)!=state_blocks_.end(); + +// const auto p = state_blocks_.emplace(state, state->getState()); + + // call addStateBlock only if first time added. + if (!registered) + { + state_blocks_.emplace(state, state->getState()); + addStateBlock(state); + } + + WOLF_DEBUG_COND(registered, "Tried adding an already registered StateBlock."); + + break; + } + case StateBlock::Notification::STATE_UPDATE: + { + const bool registered = state_blocks_.find(state)!=state_blocks_.end(); + + WOLF_DEBUG_COND(!registered, + "Updating the state of an unregistered StateBlock !"); + + // This will throw if StateBlock wasn't registered +// state_blocks_.at(state) = state->getState(); + +// state_blocks_[state] = state->getState(); + +// if (!registered) +// { +// addStateBlock(state); +// } + +// assert(state_blocks_.find(state)!=state_blocks_.end() && +// "Updating the state of an unregistered StateBlock !"); + + break; + } + case StateBlock::Notification::FIX_UPDATE: + { + WOLF_DEBUG_COND(state_blocks_.find(state)==state_blocks_.end(), + "Updating the fix state of an unregistered StateBlock !"); + + assert(state_blocks_.find(state)!=state_blocks_.end() && + "Updating the fix state of an unregistered StateBlock !"); + + updateStateBlockStatus(state); + + break; + } + case StateBlock::Notification::REMOVE: + { + WOLF_DEBUG_COND(state_blocks_.find(state)==state_blocks_.end(), + "Tried to remove a StateBlock that was not added !"); + + if (state_blocks_.erase(state) > 0) + removeStateBlock(state); + + break; + } + default: + throw std::runtime_error("SolverManager::update: State Block notification " + "must be ADD, STATE_UPDATE, FIX_UPDATE or REMOVE."); + } + } + } + + states.clear(); + + // ADD CONSTRAINTS + while (!wolf_problem_->getConstraintNotificationList().empty()) + { + switch (wolf_problem_->getConstraintNotificationList().front().notification_) + { + case Notification::ADD: + { + addConstraint(wolf_problem_->getConstraintNotificationList().front().constraint_ptr_); + + break; + } + default: + throw std::runtime_error("SolverManager::update:" + " Constraint notification must be ADD or REMOVE."); + } + + wolf_problem_->getConstraintNotificationList().pop_front(); + } + + assert(wolf_problem_->getConstraintNotificationList().empty() && + "wolf problem's constraints notification list not empty after update"); + assert(wolf_problem_->getNotifiedStateBlockList().empty() && + "wolf problem's state_blocks notification list not empty after update"); } -//void SolverManager::computeCovariances(WolfProblemPtr _problem_ptr) -//{ -//} - -void SolverManager::update(const WolfProblemPtr _problem_ptr) +wolf::ProblemPtr SolverManager::getProblemPtr() { - // IF REALLOCATION OF STATE, REMOVE EVERYTHING AND BUILD THE PROBLEM AGAIN - if (_problem_ptr->isReallocated()) - { - // todo: reallocate x - } - else - { - // ADD/UPDATE STATE UNITS - for(auto state_unit_it = _problem_ptr->getStateList().begin(); state_unit_it!=_problem_ptr->getStateList().end(); state_unit_it++) - { - if ((*state_unit_it)->getPendingStatus() == ADD_PENDING) - addStateUnit(*state_unit_it); - - else if((*state_unit_it)->getPendingStatus() == UPDATE_PENDING) - updateStateUnitStatus(*state_unit_it); - } - //std::cout << "state units updated!" << std::endl; - - // REMOVE STATE UNITS - while (!_problem_ptr->getRemovedStateList().empty()) - { - // TODO: remove state unit - //_problem_ptr->getRemovedStateList().pop_front(); - } - //std::cout << "state units removed!" << std::endl; - - // ADD CONSTRAINTS - ConstraintBaseList ctr_list; - _problem_ptr->getTrajectoryPtr()->getConstraintList(ctr_list); - //std::cout << "ctr_list.size() = " << ctr_list.size() << std::endl; - for(auto ctr_it = ctr_list.begin(); ctr_it!=ctr_list.end(); ctr_it++) - if ((*ctr_it)->getPendingStatus() == ADD_PENDING) - addConstraint(*ctr_it); - - //std::cout << "constraints updated!" << std::endl; - } + return wolf_problem_; } -void SolverManager::addConstraint(ConstraintBasePtr _corr_ptr) +std::string SolverManager::solve(const ReportVerbosity report_level) { - //TODO MatrixXs J; Vector e; - // getResidualsAndJacobian(_corr_ptr, J, e); - // solverQR->addConstraint(_corr_ptr, J, e); + // update problem + update(); -// constraint_map_[_corr_ptr->id()] = blockIdx; - _corr_ptr->setPendingStatus(NOT_PENDING); -} + std::string report = solveImpl(report_level); -void SolverManager::removeConstraint(const unsigned int& _corr_idx) -{ - // TODO -} + // update StateBlocks with optimized state value. + /// @todo whatif someone has changed the state notification during opti ?? -void SolverManager::addStateUnit(StateBlockPtr _st_ptr) -{ - //std::cout << "Adding State Unit " << _st_ptr->id() << std::endl; - //_st_ptr->print(); - - switch (_st_ptr->getStateType()) - { - case ST_COMPLEX_ANGLE: - { - // TODO - //std::cout << "Adding Complex angle Local Parametrization to the List... " << std::endl; - //ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateComplexAngle*)_st_ptr)->BLOCK_SIZE, new ComplexAngleParameterization); - break; - } - case ST_THETA: - { - //std::cout << "No Local Parametrization to be added" << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); - break; - } - case ST_POINT_1D: - { - //std::cout << "No Local Parametrization to be added" << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StatePoint1D*)_st_ptr)->BLOCK_SIZE, nullptr); - break; - } - case ST_VECTOR: - { - //std::cout << "No Local Parametrization to be added" << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); - break; - } - case ST_POINT_3D: - { - //std::cout << "No Local Parametrization to be added" << std::endl; - ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); - break; - } - default: - std::cout << "Unknown Local Parametrization type!" << std::endl; - } - if (_st_ptr->isFixed()) - updateStateUnitStatus(_st_ptr); - - _st_ptr->setPendingStatus(NOT_PENDING); + std::map<StateBlockPtr, Eigen::VectorXs>::iterator it = state_blocks_.begin(), + it_end = state_blocks_.end(); + for (; it != it_end; ++it) + { + // Avoid usuless copies + if (!it->first->isFixed()) + it->first->setState(it->second); + } + + return report; } -void SolverManager::removeAllStateUnits() +Eigen::VectorXs& SolverManager::getAssociatedMemBlock(const StateBlockPtr& state_ptr) { - std::vector<double*> parameter_blocks; + auto it = state_blocks_.find(state_ptr); - ceres_problem_->GetParameterBlocks(¶meter_blocks); + if (it == state_blocks_.end()) + throw std::runtime_error("Tried to retrieve the memory block of an unregistered StateBlock !"); - for (unsigned int i = 0; i< parameter_blocks.size(); i++) - ceres_problem_->RemoveParameterBlock(parameter_blocks[i]); + return it->second; } -void SolverManager::updateStateUnitStatus(StateBlockPtr _st_ptr) +Scalar* SolverManager::getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr) { - // TODO - -// if (!_st_ptr->isFixed()) -// ceres_problem_->SetParameterBlockVariable(_st_ptr->getPtr()); -// else if (_st_ptr->isFixed()) -// ceres_problem_->SetParameterBlockConstant(_st_ptr->getPtr()); -// else -// printf("\nERROR: Update state unit status with unknown status"); -// -// _st_ptr->setPendingStatus(NOT_PENDING); -} + auto it = state_blocks_.find(state_ptr); -ceres::CostFunction* SolverManager::createCostFunction(ConstraintBasePtr _corrPtr) -{ - //std::cout << "adding ctr " << _corrPtr->id() << std::endl; - //_corrPtr->print(); - - switch (_corrPtr->getConstraintType()) - { - case CTR_GPS_FIX_2D: - { - ConstraintGPS2D* specific_ptr = (ConstraintGPS2D*)(_corrPtr); - return new ceres::AutoDiffCostFunction<ConstraintGPS2D, - specific_ptr->residualSize, - specific_ptr->block0Size, - specific_ptr->block1Size, - specific_ptr->block2Size, - specific_ptr->block3Size, - specific_ptr->block4Size, - specific_ptr->block5Size, - specific_ptr->block6Size, - specific_ptr->block7Size, - specific_ptr->block8Size, - specific_ptr->block9Size>(specific_ptr); - break; - } - case CTR_ODOM_2D_COMPLEX_ANGLE: - { - ConstraintOdom2DComplexAngle* specific_ptr = (ConstraintOdom2DComplexAngle*)(_corrPtr); - return new ceres::AutoDiffCostFunction<ConstraintOdom2DComplexAngle, - specific_ptr->residualSize, - specific_ptr->block0Size, - specific_ptr->block1Size, - specific_ptr->block2Size, - specific_ptr->block3Size, - specific_ptr->block4Size, - specific_ptr->block5Size, - specific_ptr->block6Size, - specific_ptr->block7Size, - specific_ptr->block8Size, - specific_ptr->block9Size>(specific_ptr); - break; - } - case CTR_ODOM_2D: - { - ConstraintOdom2D* specific_ptr = (ConstraintOdom2D*)(_corrPtr); - return new ceres::AutoDiffCostFunction<ConstraintOdom2D, - specific_ptr->residualSize, - specific_ptr->block0Size, - specific_ptr->block1Size, - specific_ptr->block2Size, - specific_ptr->block3Size, - specific_ptr->block4Size, - specific_ptr->block5Size, - specific_ptr->block6Size, - specific_ptr->block7Size, - specific_ptr->block8Size, - specific_ptr->block9Size>(specific_ptr); - break; - } - case CTR_CORNER_2D: - { - ConstraintCorner2D* specific_ptr = (ConstraintCorner2D*)(_corrPtr); - return new ceres::AutoDiffCostFunction<ConstraintCorner2D, - specific_ptr->residualSize, - specific_ptr->block0Size, - specific_ptr->block1Size, - specific_ptr->block2Size, - specific_ptr->block3Size, - specific_ptr->block4Size, - specific_ptr->block5Size, - specific_ptr->block6Size, - specific_ptr->block7Size, - specific_ptr->block8Size, - specific_ptr->block9Size>(specific_ptr); - break; - } - case CTR_IMU: - { - ConstraintIMU* specific_ptr = (ConstraintIMU*)(_corrPtr); - return new ceres::AutoDiffCostFunction<ConstraintIMU, - specific_ptr->residualSize, - specific_ptr->block0Size, - specific_ptr->block1Size, - specific_ptr->block2Size, - specific_ptr->block3Size, - specific_ptr->block4Size, - specific_ptr->block5Size, - specific_ptr->block6Size, - specific_ptr->block7Size, - specific_ptr->block8Size, - specific_ptr->block9Size>(specific_ptr); - break; - } - default: - std::cout << "Unknown constraint type! Please add it in the CeresWrapper::createCostFunction()" << std::endl; - - return nullptr; - } + if (it == state_blocks_.end()) + throw std::runtime_error("Tried to retrieve the memory block of an unregistered StateBlock !"); + + return it->second.data(); } + +} // namespace wolf diff --git a/src/solver/solver_manager.h b/src/solver/solver_manager.h index 81a8e083eb30587543382814bae24f9662196335..51325380a31c9d10cba2a3039c62f2216a5b0706 100644 --- a/src/solver/solver_manager.h +++ b/src/solver/solver_manager.h @@ -1,49 +1,84 @@ -#ifndef CERES_MANAGER_H_ -#define CERES_MANAGER_H_ +#ifndef _WOLF_SOLVER_MANAGER_H_ +#define _WOLF_SOLVER_MANAGER_H_ //wolf includes -#include <constraint_GPS_2D.h> #include "../wolf.h" #include "../state_block.h" -#include "../state_point.h" -#include "../state_complex_angle.h" -#include "../state_theta.h" -#include "../constraint_sparse.h" -#include "../constraint_odom_2D_theta.h" -#include "../constraint_odom_2D_complex_angle.h" -#include "../constraint_corner_2D_theta.h" - -/** \brief solver manager for WOLF - * - */ +#include "../constraint_base.h" + +namespace wolf { +WOLF_PTR_TYPEDEFS(SolverManager) + +/** + * \brief Solver manager for WOLF + */ class SolverManager { - protected: +public: + + /** \brief Enumeration of covariance blocks to be computed + * + * Enumeration of covariance blocks to be computed + * + */ + enum class CovarianceBlocksToBeComputed : std::size_t + { + ALL, ///< All blocks and all cross-covariances + ALL_MARGINALS, ///< All marginals + ROBOT_LANDMARKS ///< marginals of landmarks and current robot pose plus cross covariances of current robot and all landmarks + }; + + /** + * \brief Enumeration for the verbosity of the solver report. + */ + enum class ReportVerbosity : std::size_t + { + QUIET = 0, + BRIEF, + FULL + }; + +protected: + ProblemPtr wolf_problem_; - public: - SolverManager(ceres::Problem::Options _options); +public: - ~SolverManager(); + SolverManager(const ProblemPtr& wolf_problem); - ceres::Solver::Summary solve(const ceres::Solver::Options& _ceres_options); + virtual ~SolverManager() = default; - //void computeCovariances(WolfProblemPtr _problem_ptr); + std::string solve(const ReportVerbosity report_level = ReportVerbosity::QUIET); - void update(const WolfProblemPtr _problem_ptr); + virtual void computeCovariances(const CovarianceBlocksToBeComputed blocks) = 0; - void addConstraint(ConstraintBasePtr _corr_ptr); + virtual void computeCovariances(const StateBlockList& st_list) = 0; - void removeConstraint(const unsigned int& _corr_idx); + virtual void update(); - void addStateUnit(StateBlockPtr _st_ptr); + ProblemPtr getProblemPtr(); - void removeAllStateUnits(); +protected: - void updateStateUnitStatus(StateBlockPtr _st_ptr); + std::map<StateBlockPtr, Eigen::VectorXs> state_blocks_; - ceres::CostFunction* createCostFunction(ConstraintBasePtr _corrPtr); + virtual Eigen::VectorXs& getAssociatedMemBlock(const StateBlockPtr& state_ptr); + virtual Scalar* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr); + + virtual std::string solveImpl(const ReportVerbosity report_level) = 0; + + virtual void addConstraint(const ConstraintBasePtr& ctr_ptr) = 0; + + virtual void removeConstraint(const ConstraintBasePtr& ctr_ptr) = 0; + + virtual void addStateBlock(const StateBlockPtr& state_ptr) = 0; + + virtual void removeStateBlock(const StateBlockPtr& state_ptr) = 0; + + virtual void updateStateBlockStatus(const StateBlockPtr& state_ptr) = 0; }; -#endif +} // namespace wolf + +#endif /* _WOLF_SOLVER_MANAGER_H_ */ diff --git a/src/solver_suitesparse/CMakeLists.txt b/src/solver_suitesparse/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..62ccd94a3e2395a59cd417458317bc1d80040747 --- /dev/null +++ b/src/solver_suitesparse/CMakeLists.txt @@ -0,0 +1,12 @@ +SET(HDRS_SOLVER_SUITESPARSE + ccolamd_ordering.h + cost_function_base.h + cost_function_sparse_base.h + cost_function_sparse.h + qr_solver.h + solver_manager.h + solver_QR.h + sparse_utils.h) +SET(SRCS_SOLVER_SUITESPARSE + solver_manager.cpp + ) diff --git a/src/solver/ccolamd_ordering.h b/src/solver_suitesparse/ccolamd_ordering.h similarity index 100% rename from src/solver/ccolamd_ordering.h rename to src/solver_suitesparse/ccolamd_ordering.h diff --git a/src/solver/cost_function_base.h b/src/solver_suitesparse/cost_function_base.h similarity index 100% rename from src/solver/cost_function_base.h rename to src/solver_suitesparse/cost_function_base.h diff --git a/src/solver/cost_function_sparse.h b/src/solver_suitesparse/cost_function_sparse.h similarity index 100% rename from src/solver/cost_function_sparse.h rename to src/solver_suitesparse/cost_function_sparse.h diff --git a/src/solver/cost_function_sparse_base.h b/src/solver_suitesparse/cost_function_sparse_base.h similarity index 100% rename from src/solver/cost_function_sparse_base.h rename to src/solver_suitesparse/cost_function_sparse_base.h diff --git a/src/solver/qr_solver.h b/src/solver_suitesparse/qr_solver.h similarity index 100% rename from src/solver/qr_solver.h rename to src/solver_suitesparse/qr_solver.h diff --git a/src/solver/solver_QR.h b/src/solver_suitesparse/solver_QR.h similarity index 100% rename from src/solver/solver_QR.h rename to src/solver_suitesparse/solver_QR.h diff --git a/src/solver_suitesparse/solver_manager.cpp b/src/solver_suitesparse/solver_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb39335b0705f8edf6222d78db36a0e18c21d504 --- /dev/null +++ b/src/solver_suitesparse/solver_manager.cpp @@ -0,0 +1,245 @@ +#include "ceres_manager.h" + +SolverManager::SolverManager() +{ + +} + +SolverManager::~SolverManager() +{ + removeAllStateUnits(); +} + +void SolverManager::solve() +{ + +} + +//void SolverManager::computeCovariances(WolfProblemPtr _problem_ptr) +//{ +//} + +void SolverManager::update(const WolfProblemPtr _problem_ptr) +{ + // IF REALLOCATION OF STATE, REMOVE EVERYTHING AND BUILD THE PROBLEM AGAIN + if (_problem_ptr->isReallocated()) + { + // todo: reallocate x + } + else + { + // ADD/UPDATE STATE UNITS + for(auto state_unit_it = _problem_ptr->getStateList().begin(); state_unit_it!=_problem_ptr->getStateList().end(); state_unit_it++) + { + if ((*state_unit_it)->getPendingStatus() == ADD_PENDING) + addStateUnit(*state_unit_it); + + else if((*state_unit_it)->getPendingStatus() == UPDATE_PENDING) + updateStateUnitStatus(*state_unit_it); + } + //std::cout << "state units updated!" << std::endl; + + // REMOVE STATE UNITS + while (!_problem_ptr->getRemovedStateList().empty()) + { + // TODO: remove state unit + //_problem_ptr->getRemovedStateList().pop_front(); + } + //std::cout << "state units removed!" << std::endl; + + // ADD CONSTRAINTS + ConstraintBaseList ctr_list; + _problem_ptr->getTrajectoryPtr()->getConstraintList(ctr_list); + //std::cout << "ctr_list.size() = " << ctr_list.size() << std::endl; + for(auto ctr_it = ctr_list.begin(); ctr_it!=ctr_list.end(); ctr_it++) + if ((*ctr_it)->getPendingStatus() == ADD_PENDING) + addConstraint(*ctr_it); + + //std::cout << "constraints updated!" << std::endl; + } +} + +void SolverManager::addConstraint(ConstraintBasePtr _corr_ptr) +{ + //TODO MatrixXs J; Vector e; + // getResidualsAndJacobian(_corr_ptr, J, e); + // solverQR->addConstraint(_corr_ptr, J, e); + +// constraint_map_[_corr_ptr->id()] = blockIdx; + _corr_ptr->setPendingStatus(NOT_PENDING); +} + +void SolverManager::removeConstraint(const unsigned int& _corr_idx) +{ + // TODO +} + +void SolverManager::addStateUnit(StateBlockPtr _st_ptr) +{ + //std::cout << "Adding State Unit " << _st_ptr->id() << std::endl; + //_st_ptr->print(); + + switch (_st_ptr->getStateType()) + { + case ST_COMPLEX_ANGLE: + { + // TODO + //std::cout << "Adding Complex angle Local Parametrization to the List... " << std::endl; + //ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateComplexAngle*)_st_ptr)->BLOCK_SIZE, new ComplexAngleParameterization); + break; + } + case ST_THETA: + { + //std::cout << "No Local Parametrization to be added" << std::endl; + ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); + break; + } + case ST_POINT_1D: + { + //std::cout << "No Local Parametrization to be added" << std::endl; + ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StatePoint1D*)_st_ptr)->BLOCK_SIZE, nullptr); + break; + } + case ST_VECTOR: + { + //std::cout << "No Local Parametrization to be added" << std::endl; + ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); + break; + } + case ST_POINT_3D: + { + //std::cout << "No Local Parametrization to be added" << std::endl; + ceres_problem_->AddParameterBlock(_st_ptr->getPtr(), ((StateBlockPtr)_st_ptr)->BLOCK_SIZE, nullptr); + break; + } + default: + std::cout << "Unknown Local Parametrization type!" << std::endl; + } + if (_st_ptr->isFixed()) + updateStateUnitStatus(_st_ptr); + + _st_ptr->setPendingStatus(NOT_PENDING); +} + +void SolverManager::removeAllStateUnits() +{ + std::vector<double*> parameter_blocks; + + ceres_problem_->GetParameterBlocks(¶meter_blocks); + + for (unsigned int i = 0; i< parameter_blocks.size(); i++) + ceres_problem_->RemoveParameterBlock(parameter_blocks[i]); +} + +void SolverManager::updateStateUnitStatus(StateBlockPtr _st_ptr) +{ + // TODO + +// if (!_st_ptr->isFixed()) +// ceres_problem_->SetParameterBlockVariable(_st_ptr->getPtr()); +// else if (_st_ptr->isFixed()) +// ceres_problem_->SetParameterBlockConstant(_st_ptr->getPtr()); +// else +// printf("\nERROR: Update state unit status with unknown status"); +// +// _st_ptr->setPendingStatus(NOT_PENDING); +} + +ceres::CostFunction* SolverManager::createCostFunction(ConstraintBasePtr _corrPtr) +{ + //std::cout << "adding ctr " << _corrPtr->id() << std::endl; + //_corrPtr->print(); + + switch (_corrPtr->getConstraintType()) + { + case CTR_GPS_FIX_2D: + { + ConstraintGPS2D* specific_ptr = (ConstraintGPS2D*)(_corrPtr); + return new ceres::AutoDiffCostFunction<ConstraintGPS2D, + specific_ptr->residualSize, + specific_ptr->block0Size, + specific_ptr->block1Size, + specific_ptr->block2Size, + specific_ptr->block3Size, + specific_ptr->block4Size, + specific_ptr->block5Size, + specific_ptr->block6Size, + specific_ptr->block7Size, + specific_ptr->block8Size, + specific_ptr->block9Size>(specific_ptr); + break; + } + case CTR_ODOM_2D_COMPLEX_ANGLE: + { + ConstraintOdom2DComplexAngle* specific_ptr = (ConstraintOdom2DComplexAngle*)(_corrPtr); + return new ceres::AutoDiffCostFunction<ConstraintOdom2DComplexAngle, + specific_ptr->residualSize, + specific_ptr->block0Size, + specific_ptr->block1Size, + specific_ptr->block2Size, + specific_ptr->block3Size, + specific_ptr->block4Size, + specific_ptr->block5Size, + specific_ptr->block6Size, + specific_ptr->block7Size, + specific_ptr->block8Size, + specific_ptr->block9Size>(specific_ptr); + break; + } + case CTR_ODOM_2D: + { + ConstraintOdom2D* specific_ptr = (ConstraintOdom2D*)(_corrPtr); + return new ceres::AutoDiffCostFunction<ConstraintOdom2D, + specific_ptr->residualSize, + specific_ptr->block0Size, + specific_ptr->block1Size, + specific_ptr->block2Size, + specific_ptr->block3Size, + specific_ptr->block4Size, + specific_ptr->block5Size, + specific_ptr->block6Size, + specific_ptr->block7Size, + specific_ptr->block8Size, + specific_ptr->block9Size>(specific_ptr); + break; + } + case CTR_CORNER_2D: + { + ConstraintCorner2D* specific_ptr = (ConstraintCorner2D*)(_corrPtr); + return new ceres::AutoDiffCostFunction<ConstraintCorner2D, + specific_ptr->residualSize, + specific_ptr->block0Size, + specific_ptr->block1Size, + specific_ptr->block2Size, + specific_ptr->block3Size, + specific_ptr->block4Size, + specific_ptr->block5Size, + specific_ptr->block6Size, + specific_ptr->block7Size, + specific_ptr->block8Size, + specific_ptr->block9Size>(specific_ptr); + break; + } + case CTR_IMU: + { + ConstraintIMU* specific_ptr = (ConstraintIMU*)(_corrPtr); + return new ceres::AutoDiffCostFunction<ConstraintIMU, + specific_ptr->residualSize, + specific_ptr->block0Size, + specific_ptr->block1Size, + specific_ptr->block2Size, + specific_ptr->block3Size, + specific_ptr->block4Size, + specific_ptr->block5Size, + specific_ptr->block6Size, + specific_ptr->block7Size, + specific_ptr->block8Size, + specific_ptr->block9Size>(specific_ptr); + break; + } + default: + std::cout << "Unknown constraint type! Please add it in the CeresWrapper::createCostFunction()" << std::endl; + + return nullptr; + } +} diff --git a/src/solver_suitesparse/solver_manager.h b/src/solver_suitesparse/solver_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..81a8e083eb30587543382814bae24f9662196335 --- /dev/null +++ b/src/solver_suitesparse/solver_manager.h @@ -0,0 +1,49 @@ +#ifndef CERES_MANAGER_H_ +#define CERES_MANAGER_H_ + +//wolf includes +#include <constraint_GPS_2D.h> +#include "../wolf.h" +#include "../state_block.h" +#include "../state_point.h" +#include "../state_complex_angle.h" +#include "../state_theta.h" +#include "../constraint_sparse.h" +#include "../constraint_odom_2D_theta.h" +#include "../constraint_odom_2D_complex_angle.h" +#include "../constraint_corner_2D_theta.h" + +/** \brief solver manager for WOLF + * + */ + +class SolverManager +{ + protected: + + + public: + SolverManager(ceres::Problem::Options _options); + + ~SolverManager(); + + ceres::Solver::Summary solve(const ceres::Solver::Options& _ceres_options); + + //void computeCovariances(WolfProblemPtr _problem_ptr); + + void update(const WolfProblemPtr _problem_ptr); + + void addConstraint(ConstraintBasePtr _corr_ptr); + + void removeConstraint(const unsigned int& _corr_idx); + + void addStateUnit(StateBlockPtr _st_ptr); + + void removeAllStateUnits(); + + void updateStateUnitStatus(StateBlockPtr _st_ptr); + + ceres::CostFunction* createCostFunction(ConstraintBasePtr _corrPtr); +}; + +#endif diff --git a/src/solver/sparse_utils.h b/src/solver_suitesparse/sparse_utils.h similarity index 100% rename from src/solver/sparse_utils.h rename to src/solver_suitesparse/sparse_utils.h diff --git a/src/state_block.h b/src/state_block.h index 7903ceb748e1700495c83f6bae02efc869dfe2e1..780b0b8bf107eb0897f033f183e85b19d7724cba 100644 --- a/src/state_block.h +++ b/src/state_block.h @@ -29,14 +29,30 @@ namespace wolf { */ class StateBlock { +public: + + enum class Notification : std::size_t + { + ADD = 0, + REMOVE, + STATE_UPDATE, + FIX_UPDATE + }; + + using Notifications = std::list<Notification>; + protected: + + mutable Notifications notifications_; + mutable std::mutex notifictions_mut_; + NodeBaseWPtr node_ptr_; //< pointer to the wolf Node owning this StateBlock bool fixed_; ///< Key to indicate whether the state is fixed or not Eigen::VectorXs state_; ///< State vector storing the state values LocalParametrizationBasePtr local_param_ptr_; ///< Local parametrization useful for optimizing in the tangent space to the manifold - + public: /** \brief Constructor from size * @@ -53,18 +69,14 @@ class StateBlock * \param _local_param_ptr pointer to the local parametrization for the block **/ StateBlock(const Eigen::VectorXs& _state, bool _fixed = false, LocalParametrizationBasePtr _local_param_ptr = nullptr); - + /** \brief Destructor **/ virtual ~StateBlock(); - /** \brief Returns the pointer to the first element of the state - **/ - Scalar* getPtr(); - /** \brief Returns the state vector **/ - const Eigen::VectorXs& getState() const; + Eigen::VectorXs getState() const; /** \brief Sets the state vector **/ @@ -94,14 +106,19 @@ class StateBlock void setFixed(bool _fixed); - bool hasLocalParametrization(); + bool hasLocalParametrization() const; - LocalParametrizationBasePtr getLocalParametrizationPtr(); + LocalParametrizationBasePtr getLocalParametrizationPtr() const; void setLocalParametrizationPtr(LocalParametrizationBasePtr _local_param); void removeLocalParametrization(); + void addNotification(const StateBlock::Notification _new_notification); + + StateBlock::Notifications consumeNotifications() const; + + bool hasNotifications() const; }; } // namespace wolf @@ -112,6 +129,7 @@ class StateBlock namespace wolf { inline StateBlock::StateBlock(const Eigen::VectorXs& _state, bool _fixed, LocalParametrizationBasePtr _local_param_ptr) : +// notifications_{Notification::ADD}, node_ptr_(), // nullptr fixed_(_fixed), state_(_state), @@ -121,6 +139,7 @@ inline StateBlock::StateBlock(const Eigen::VectorXs& _state, bool _fixed, LocalP } inline StateBlock::StateBlock(const unsigned int _size, bool _fixed, LocalParametrizationBasePtr _local_param_ptr) : +// notifications_{Notification::ADD}, node_ptr_(), // nullptr fixed_(_fixed), state_(Eigen::VectorXs::Zero(_size)), @@ -135,12 +154,7 @@ inline StateBlock::~StateBlock() // std::cout << "destructed -sb" << std::endl; } -inline Scalar* StateBlock::getPtr() -{ - return state_.data(); -} - -inline const Eigen::VectorXs& StateBlock::getState() const +inline Eigen::VectorXs StateBlock::getState() const { return state_; } @@ -149,6 +163,7 @@ inline void StateBlock::setState(const Eigen::VectorXs& _state) { assert(_state.size() == state_.size()); state_ = _state; + addNotification(Notification::STATE_UPDATE); } inline unsigned int StateBlock::getSize() const @@ -170,25 +185,26 @@ inline bool StateBlock::isFixed() const inline void StateBlock::fix() { - fixed_ = true; + setFixed(true); } inline void StateBlock::unfix() { - fixed_ = false; + setFixed(false); } inline void StateBlock::setFixed(bool _fixed) { fixed_ = _fixed; + addNotification(Notification::FIX_UPDATE); } -inline bool StateBlock::hasLocalParametrization() +inline bool StateBlock::hasLocalParametrization() const { return (local_param_ptr_ != nullptr); } -inline LocalParametrizationBasePtr StateBlock::getLocalParametrizationPtr() +inline LocalParametrizationBasePtr StateBlock::getLocalParametrizationPtr() const { return local_param_ptr_; } @@ -205,6 +221,24 @@ inline void StateBlock::setLocalParametrizationPtr(LocalParametrizationBasePtr _ local_param_ptr_ = _local_param; } +inline void StateBlock::addNotification(const StateBlock::Notification _new_notification) +{ + std::lock_guard<std::mutex> lock(notifictions_mut_); + notifications_.emplace_back(_new_notification); +} + +inline StateBlock::Notifications StateBlock::consumeNotifications() const +{ + std::lock_guard<std::mutex> lock(notifictions_mut_); + return std::move(notifications_); +} + +inline bool StateBlock::hasNotifications() const +{ + std::lock_guard<std::mutex> lock(notifictions_mut_); + return !notifications_.empty(); +} + } // namespace wolf #endif diff --git a/src/test/gtest_IMU.cpp b/src/test/gtest_IMU.cpp index 0a23dff8cd4b85df626891719b345532dffc515d..38dfbc223a2e3137c503eef65ff343e379265365 100644 --- a/src/test/gtest_IMU.cpp +++ b/src/test/gtest_IMU.cpp @@ -521,7 +521,7 @@ class Process_Constraint_IMU : public testing::Test - string solveProblem(int verbose = 1) + string solveProblem(SolverManager::ReportVerbosity verbose = SolverManager::ReportVerbosity::BRIEF) { string report = ceres_manager->solve(verbose); @@ -544,7 +544,7 @@ class Process_Constraint_IMU : public testing::Test - string runAll(int verbose) + string runAll(SolverManager::ReportVerbosity verbose) { configureAll(); integrateAll(); @@ -729,7 +729,7 @@ TEST_F(Process_Constraint_IMU, MotionConstant_PQV_b__PQV_b) // F_ixed___e_stimat // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -822,7 +822,7 @@ TEST_F(Process_Constraint_IMU, MotionConstant_pqv_b__PQV_b) // F_ixed___e_stimat // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -868,7 +868,7 @@ TEST_F(Process_Constraint_IMU, MotionConstant_pqV_b__PQv_b) // F_ixed___e_stimat // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -914,7 +914,7 @@ TEST_F(Process_Constraint_IMU, MotionRandom_PQV_b__PQV_b) // F_ixed___e_stimated // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -960,7 +960,7 @@ TEST_F(Process_Constraint_IMU, MotionRandom_pqV_b__PQv_b) // F_ixed___e_stimated // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1005,7 +1005,7 @@ TEST_F(Process_Constraint_IMU, MotionRandom_pqV_b__pQV_b) // F_ixed___e_stimated // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1050,7 +1050,7 @@ TEST_F(Process_Constraint_IMU, MotionConstant_NonNullState_PQV_b__PQV_b) // F_ix // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1095,7 +1095,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstantRotation_PQV_b__PQV_b) // F_ixe // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1140,7 +1140,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstantRotation_PQV_b__PQv_b) // F_ixe // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1185,7 +1185,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstantRotation_PQV_b__Pqv_b) // F_ixe // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1230,7 +1230,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstantRotation_PQV_b__pQv_b) // F_ixe // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1275,7 +1275,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstantRotation_PQV_b__pqv_b) // F_ixe // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1320,7 +1320,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstant_pqv_b__pqV_b) // F_ixed___e_st // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1365,7 +1365,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionConstant_pqV_b__pqv_b) // F_ixed___e_st // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1410,7 +1410,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionRandom_PQV_b__pqv_b) // F_ixed___e_stim // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1455,7 +1455,7 @@ TEST_F(Process_Constraint_IMU_ODO, MotionRandom_PqV_b__pqV_b) // F_ixed___e_stim // ===================================== RUN ALL - string report = runAll(1); + string report = runAll(SolverManager::ReportVerbosity::BRIEF); // printAll(report); @@ -1503,7 +1503,7 @@ TEST_F(Process_Constraint_IMU_ODO, RecoverTrajectory_MotionRandom_PqV_b__pqV_b) configureAll(); integrateAllTrajectories(); buildProblem(); - string report = solveProblem(1); + string report = solveProblem(SolverManager::ReportVerbosity::BRIEF); assertAll(); diff --git a/src/test/gtest_constraint_absolute.cpp b/src/test/gtest_constraint_absolute.cpp index 52adcd099403218395990b69ed857da62259d507..80a6579ae459d7932e7c0e4df9b95e48a76ce326 100644 --- a/src/test/gtest_constraint_absolute.cpp +++ b/src/test/gtest_constraint_absolute.cpp @@ -70,7 +70,7 @@ TEST(ConstraintBlockAbs, ctr_block_abs_p_solve) frm0->setState(x0); // solve for frm0 - std::string brief_report = ceres_mgr.solve(1); + std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only orientation is constrained ASSERT_MATRIX_APPROX(frm0->getState().head<3>(), pose10.head<3>(), 1e-6); @@ -97,7 +97,7 @@ TEST(ConstraintBlockAbs, ctr_block_abs_v_solve) frm0->setState(x0); // solve for frm0 - std::string brief_report = ceres_mgr.solve(1); + std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only velocity is constrained ASSERT_MATRIX_APPROX(frm0->getState().tail<3>(), pose10.tail<3>(), 1e-6); @@ -124,7 +124,7 @@ TEST(ConstraintQuatAbs, ctr_block_abs_o_solve) frm0->setState(x0); // solve for frm0 - std::string brief_report = ceres_mgr.solve(1); + std::string brief_report = ceres_mgr.solve(wolf::SolverManager::ReportVerbosity::BRIEF); //only velocity is constrained ASSERT_MATRIX_APPROX(frm0->getState().segment<4>(3), pose10.segment<4>(3), 1e-6); diff --git a/src/test/gtest_constraint_autodiff.cpp b/src/test/gtest_constraint_autodiff.cpp index 52b5d1c121987779fb20661319f5b8f1a27fd8ad..c5820537f54d0aaf8e251cc4867a88b82f1d0e33 100644 --- a/src/test/gtest_constraint_autodiff.cpp +++ b/src/test/gtest_constraint_autodiff.cpp @@ -74,7 +74,14 @@ TEST(CaptureAutodiff, ResidualOdom2d) fr1_ptr->addConstrainedBy(constraint_ptr); // EVALUATE - std::vector<Scalar*> states_ptr({fr1_ptr->getPPtr()->getPtr(), fr1_ptr->getOPtr()->getPtr(), fr2_ptr->getPPtr()->getPtr(), fr2_ptr->getOPtr()->getPtr()}); + + Eigen::VectorXs fr1_pstate = fr1_ptr->getPPtr()->getState(); + Eigen::VectorXs fr1_ostate = fr1_ptr->getOPtr()->getState(); + Eigen::VectorXs fr2_pstate = fr2_ptr->getPPtr()->getState(); + Eigen::VectorXs fr2_ostate = fr2_ptr->getOPtr()->getState(); + + std::vector<Scalar*> states_ptr({fr1_pstate.data(), fr1_ostate.data(), fr2_pstate.data(), fr2_ostate.data()}); + double const* const* parameters = states_ptr.data(); Eigen::VectorXs residuals(constraint_ptr->getSize()); constraint_ptr->evaluate(parameters, residuals.data(), nullptr); @@ -111,7 +118,14 @@ TEST(CaptureAutodiff, JacobianOdom2d) fr1_ptr->addConstrainedBy(constraint_ptr); // COMPUTE JACOBIANS - std::vector<const Scalar*> states_ptr({fr1_ptr->getPPtr()->getPtr(), fr1_ptr->getOPtr()->getPtr(), fr2_ptr->getPPtr()->getPtr(), fr2_ptr->getOPtr()->getPtr()}); + + const Eigen::VectorXs fr1_pstate = fr1_ptr->getPPtr()->getState(); + const Eigen::VectorXs fr1_ostate = fr1_ptr->getOPtr()->getState(); + const Eigen::VectorXs fr2_pstate = fr2_ptr->getPPtr()->getState(); + const Eigen::VectorXs fr2_ostate = fr2_ptr->getOPtr()->getState(); + + std::vector<const Scalar*> states_ptr({fr1_pstate.data(), fr1_ostate.data(), fr2_pstate.data(), fr2_ostate.data()}); + std::vector<Eigen::MatrixXs> Jauto; Eigen::VectorXs residuals(constraint_ptr->getSize()); constraint_ptr->evaluate(states_ptr, residuals, Jauto); @@ -186,7 +200,14 @@ TEST(CaptureAutodiff, AutodiffVsAnalytic) fr1_ptr->addConstrainedBy(ctr_analytic_ptr); // COMPUTE JACOBIANS - std::vector<const Scalar*> states_ptr({fr1_ptr->getPPtr()->getPtr(), fr1_ptr->getOPtr()->getPtr(), fr2_ptr->getPPtr()->getPtr(), fr2_ptr->getOPtr()->getPtr()}); + + const Eigen::VectorXs fr1_pstate = fr1_ptr->getPPtr()->getState(); + const Eigen::VectorXs fr1_ostate = fr1_ptr->getOPtr()->getState(); + const Eigen::VectorXs fr2_pstate = fr2_ptr->getPPtr()->getState(); + const Eigen::VectorXs fr2_ostate = fr2_ptr->getOPtr()->getState(); + + std::vector<const Scalar*> states_ptr({fr1_pstate.data(), fr1_ostate.data(), fr2_pstate.data(), fr2_ostate.data()}); + std::vector<Eigen::MatrixXs> Jautodiff, Janalytic; Eigen::VectorXs residuals(ctr_autodiff_ptr->getSize()); clock_t t = clock(); diff --git a/src/test/gtest_constraint_autodiff_distance_3D.cpp b/src/test/gtest_constraint_autodiff_distance_3D.cpp index 768be80e93b39146ebc42a91b63f7b3011e42066..bc6e402e423c2f6531a94591a1add61733872607 100644 --- a/src/test/gtest_constraint_autodiff_distance_3D.cpp +++ b/src/test/gtest_constraint_autodiff_distance_3D.cpp @@ -98,7 +98,7 @@ TEST_F(ConstraintAutodiffDistance3D_Test, solve) Scalar measurement = 1.400; f2->setMeasurement(Vector1s(measurement)); - std::string report = ceres_manager->solve(2); + std::string report = ceres_manager->solve(SolverManager::ReportVerbosity::QUIET); // Check distance between F1 and F2 positions -- must match the measurement ASSERT_NEAR( (F1->getPPtr()->getState() - F2->getPPtr()->getState()).norm(), measurement, 1e-10); diff --git a/src/test/gtest_constraint_odom_3D.cpp b/src/test/gtest_constraint_odom_3D.cpp index 1fba7cd1dd83b88824adcfb7c623be64ce34589c..f3b9e0cca1770a6b06d6f2a51c408d54d982a69b 100644 --- a/src/test/gtest_constraint_odom_3D.cpp +++ b/src/test/gtest_constraint_odom_3D.cpp @@ -69,7 +69,7 @@ TEST(ConstraintOdom3D, fix_0_solve) frm1->setState(x1); // solve for frm1 - std::string report = ceres_mgr.solve(1); + std::string report = ceres_mgr.solve(SolverManager::ReportVerbosity::BRIEF); ASSERT_MATRIX_APPROX(frm1->getState(), delta, 1e-6); @@ -83,7 +83,7 @@ TEST(ConstraintOdom3D, fix_1_solve) frm0->setState(x0); // solve for frm0 - std::string brief_report = ceres_mgr.solve(1); + std::string brief_report = ceres_mgr.solve(SolverManager::ReportVerbosity::BRIEF); ASSERT_MATRIX_APPROX(frm0->getState(), problem->zeroState(), 1e-6); } diff --git a/src/test/gtest_constraint_pose_2D.cpp b/src/test/gtest_constraint_pose_2D.cpp index 220ead9cfdd33baddcc525966890ff82b0b73754..c98de12b0f2dd05628ff905b8877e40daa80ba16 100644 --- a/src/test/gtest_constraint_pose_2D.cpp +++ b/src/test/gtest_constraint_pose_2D.cpp @@ -59,7 +59,7 @@ TEST(ConstraintPose2D, solve) frm0->setState(x0); // solve for frm0 - std::string report = ceres_mgr.solve(0); // 0: nothing, 1: BriefReport, 2: FullReport + std::string report = ceres_mgr.solve(SolverManager::ReportVerbosity::QUIET); // 0: nothing, 1: BriefReport, 2: FullReport ASSERT_MATRIX_APPROX(frm0->getState(), pose, 1e-6); diff --git a/src/test/gtest_constraint_pose_3D.cpp b/src/test/gtest_constraint_pose_3D.cpp index a22d361c842b21e80c2a63dcae5d04f621fc744d..77604701ad57fc9851169a599822d10e6beb7c77 100644 --- a/src/test/gtest_constraint_pose_3D.cpp +++ b/src/test/gtest_constraint_pose_3D.cpp @@ -67,7 +67,7 @@ TEST(ConstraintPose3D, solve) frm0->setState(x0); // solve for frm0 - std::string brief_report = ceres_mgr.solve(1); + std::string brief_report = ceres_mgr.solve(SolverManager::ReportVerbosity::FULL); ASSERT_MATRIX_APPROX(frm0->getState(), pose7, 1e-6); diff --git a/src/test/gtest_odom_2D.cpp b/src/test/gtest_odom_2D.cpp index bd101f24074cf8fc426a8551bcce85e1bd94e97a..b8bb7388cad12f319a37e053d747df66ce0b63a5 100644 --- a/src/test/gtest_odom_2D.cpp +++ b/src/test/gtest_odom_2D.cpp @@ -153,10 +153,10 @@ TEST(Odom2D, ConstraintFix_and_ConstraintOdom2D) F0->setState(Vector3s(1,2,3)); F1->setState(Vector3s(2,3,1)); F2->setState(Vector3s(3,1,2)); - std::string report = ceres_manager.solve(1); + std::string report = ceres_manager.solve(SolverManager::ReportVerbosity::FULL); // std::cout << report << std::endl; - ceres_manager.computeCovariances(ALL_MARGINALS); + ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); // show(Pr); Matrix3s P1, P2; @@ -211,8 +211,8 @@ TEST(Odom2D, VoteForKfAndSolve) // Origin Key Frame FrameBasePtr origin_frame = problem->setPrior(x0, P0, t0, dt/2); - ceres_manager.solve(0); - ceres_manager.computeCovariances(ALL_MARGINALS); + ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF); + ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); // std::cout << "Initial pose : " << problem->getCurrentState().transpose() << std::endl; // std::cout << "Initial covariance : " << std::endl << problem->getLastKeyFrameCovariance() << std::endl; @@ -280,9 +280,9 @@ TEST(Odom2D, VoteForKfAndSolve) } // Solve - std::string report = ceres_manager.solve(1); + std::string report = ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF); // std::cout << report << std::endl; - ceres_manager.computeCovariances(ALL_MARGINALS); + ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); ASSERT_MATRIX_APPROX(problem->getLastKeyFrameCovariance() , integrated_cov_vector[5], 1e-6); } @@ -402,9 +402,9 @@ TEST(Odom2D, KF_callback) MotionBuffer key_buffer_n = key_capture_n->getBuffer(); - std::string report = ceres_manager.solve(1); + std::string report = ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF); // std::cout << report << std::endl; - ceres_manager.computeCovariances(ALL_MARGINALS); + ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); ASSERT_POSE2D_APPROX(problem->getLastKeyFramePtr()->getState() , integrated_pose_vector[n_split], 1e-6); ASSERT_MATRIX_APPROX(problem->getLastKeyFrameCovariance() , integrated_cov_vector [n_split], 1e-6); @@ -437,8 +437,8 @@ TEST(Odom2D, KF_callback) keyframe_1->setState(Vector3s(2,3,1)); keyframe_2->setState(Vector3s(3,1,2)); - report = ceres_manager.solve(1); - ceres_manager.computeCovariances(ALL_MARGINALS); + report = ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF); + ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); // check the split KF ASSERT_POSE2D_APPROX(keyframe_1->getState() , integrated_pose_vector[m_split], 1e-6); @@ -455,7 +455,7 @@ TEST(Odom2D, KF_callback) t += dt; // WOLF_DEBUG(" estimated(", t, ") = ", problem->getState(t).transpose()); // WOLF_DEBUG("ground truth(", t, ") = ", integrated_pose_vector[n].transpose()); - ASSERT_MATRIX_APPROX(problem->getState(t), integrated_pose_vector[n], 1e-6); + EXPECT_POSE2D_APPROX(problem->getState(t), integrated_pose_vector[n], 1e-6); } } diff --git a/src/test/gtest_problem.cpp b/src/test/gtest_problem.cpp index 1d0a26ae8e027befecc08dfc62e46a36abe516e6..420e9b271a16e70c41bd72df083f9ae6137cf5eb 100644 --- a/src/test/gtest_problem.cpp +++ b/src/test/gtest_problem.cpp @@ -79,7 +79,7 @@ TEST(Problem, Installers) SensorBasePtr S = P->installSensor ("ODOM 3D", "odometer", xs, wolf_root + "/src/examples/sensor_odom_3D.yaml"); // install processor tracker (dummy installation under an Odometry sensor -- it's OK for this test) - ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(ProcessorTrackerFeatureDummy(0.1, 5, 10)); + ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(0.1, 5, 10); S->addProcessor(pt); // check motion processor IS NOT set @@ -210,21 +210,21 @@ TEST(Problem, StateBlocks) // 2 state blocks, fixed SensorBasePtr Sm = P->installSensor ("ODOM 3D", "odometer",xs, wolf_root + "/src/examples/sensor_odom_3D.yaml"); ASSERT_EQ(P->getStateBlockList().size(), 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2); // 3 state blocks, fixed SensorBasePtr St = P->installSensor ("CAMERA", "camera", xs, wolf_root + "/src/examples/camera_params_ueye_sim.yaml"); ASSERT_EQ(P->getStateBlockList().size(), 2 + 3); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2 + 3); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2 + 3); - ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(ProcessorTrackerFeatureDummy(0.1, 5, 10)); + ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(0.1, 5, 10); St->addProcessor(pt); ProcessorBasePtr pm = P->installProcessor("ODOM 3D", "odom integrator", "odometer", wolf_root + "/src/examples/processor_odom_3D.yaml"); // 2 state blocks, estimated P->emplaceFrame("PO 3D", KEY_FRAME, xs, 0); ASSERT_EQ(P->getStateBlockList().size(), 2 + 3 + 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2 + 3 + 2); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2 + 3 + 2); // P->print(4,1,1,1); @@ -232,7 +232,7 @@ TEST(Problem, StateBlocks) // change some SB properties St->unfixExtrinsics(); ASSERT_EQ(P->getStateBlockList().size(), 2 + 3 + 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2 + 3 + 2 + 2); // XXX: 2 more notifications on the same SB! + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2 + 3 + 2 /*+ 2*/); // XXX: 2 more notifications on the same SB! // P->print(4,1,1,1); } @@ -246,7 +246,7 @@ TEST(Problem, Covariances) SensorBasePtr Sm = P->installSensor ("ODOM 3D", "odometer",xs, wolf_root + "/src/examples/sensor_odom_3D.yaml"); SensorBasePtr St = P->installSensor ("CAMERA", "camera", xs, wolf_root + "/src/examples/camera_params_ueye_sim.yaml"); - ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(ProcessorTrackerFeatureDummy(0.1, 5, 10)); + ProcessorBasePtr pt = std::make_shared<ProcessorTrackerFeatureDummy>(0.1, 5, 10); St->addProcessor(pt); ProcessorBasePtr pm = P->installProcessor("ODOM 3D", "odom integrator", "odometer", wolf_root + "/src/examples/processor_odom_3D.yaml"); diff --git a/src/test/gtest_trajectory.cpp b/src/test/gtest_trajectory.cpp index f6835809e5074b2bcf30c789c8e38aaff0e268bb..0c1b2cdf7597f22c042c3c09ad61a77943cfdcaf 100644 --- a/src/test/gtest_trajectory.cpp +++ b/src/test/gtest_trajectory.cpp @@ -17,6 +17,63 @@ using namespace wolf; +struct DummyNotificationProcessor +{ + DummyNotificationProcessor(ProblemPtr _problem) + : problem_(_problem) + { + // + } + + void update() + { + if (problem_ == nullptr) + { + FAIL() << "problem_ is nullptr !"; + } + + StateBlockList& states = problem_->getNotifiedStateBlockList(); + + for (StateBlockPtr& state : states) + { + const auto notifications = state->consumeNotifications(); + + for (const auto notif : notifications) + { + switch (notif) + { + case StateBlock::Notification::ADD: + { + break; + } + case StateBlock::Notification::STATE_UPDATE: + { + break; + } + case StateBlock::Notification::FIX_UPDATE: + { + break; + } + case StateBlock::Notification::REMOVE: + { + break; + } + default: + throw std::runtime_error("SolverManager::update: State Block notification " + "must be ADD, STATE_UPDATE, FIX_UPDATE, REMOVE or ENABLED."); + } + } + + ASSERT_FALSE(state->hasNotifications()); + } + + states.clear(); + } + + ProblemPtr problem_; +}; + + /// Set to true if you want debug info bool debug = false; @@ -63,6 +120,8 @@ TEST(TrajectoryBase, Add_Remove_Frame) ProblemPtr P = Problem::create("PO 2D"); TrajectoryBasePtr T = P->getTrajectoryPtr(); + DummyNotificationProcessor N(P); + // Trajectory status: // kf1 kf2 f3 frames // 1 2 3 time stamps @@ -77,29 +136,31 @@ TEST(TrajectoryBase, Add_Remove_Frame) if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 1); ASSERT_EQ(P->getStateBlockList(). size(), 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2); T->addFrame(f2); // KF if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 2); ASSERT_EQ(P->getStateBlockList(). size(), 4); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 4); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 4); T->addFrame(f3); // F if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 3); ASSERT_EQ(P->getStateBlockList(). size(), 4); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 4); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 4); ASSERT_EQ(T->getLastFramePtr()->id(), f3->id()); ASSERT_EQ(T->getLastKeyFramePtr()->id(), f2->id()); + N.update(); + // remove frames and keyframes f2->remove(); // KF if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 2); ASSERT_EQ(P->getStateBlockList(). size(), 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2); ASSERT_EQ(T->getLastFramePtr()->id(), f3->id()); ASSERT_EQ(T->getLastKeyFramePtr()->id(), f1->id()); @@ -108,7 +169,7 @@ TEST(TrajectoryBase, Add_Remove_Frame) if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 1); ASSERT_EQ(P->getStateBlockList(). size(), 2); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 2); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 2); ASSERT_EQ(T->getLastKeyFramePtr()->id(), f1->id()); @@ -116,8 +177,11 @@ TEST(TrajectoryBase, Add_Remove_Frame) if (debug) P->print(2,0,0,0); ASSERT_EQ(T->getFrameList(). size(), 0); ASSERT_EQ(P->getStateBlockList(). size(), 0); - ASSERT_EQ(P->getStateBlockNotificationList().size(), 0); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 4); + + N.update(); + ASSERT_EQ(P->getNotifiedStateBlockList().size(), 0); } TEST(TrajectoryBase, KeyFramesAreSorted)