现在返回到最初的node_main.cc
中的Run
函数,还有一句node.RunFinalOptimization();
,所有轨迹结束时,再执行一次全局优化。 其实就是MapBuilderBridge::RunFinalOptimization
—— PoseGraph2D::RunFinalOptimization
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void PoseGraph2D::RunFinalOptimization () { { AddWorkItem ([this ]() LOCKS_EXCLUDED (mutex_) { absl::MutexLock locker (&mutex_); optimization_problem_->SetMaxNumIterations ( options_.max_num_final_iterations ()); return WorkItem::Result::kRunOptimization; }); AddWorkItem ([this ]() LOCKS_EXCLUDED (mutex_) { absl::MutexLock locker (&mutex_); optimization_problem_->SetMaxNumIterations ( options_.optimization_problem_options () .ceres_solver_options () .max_num_iterations ()); return WorkItem::Result::kDoNotRunOptimization; }); } WaitForAllComputations (); }
在建图结束之后会运行一个新的全局优化,不要求实时性,迭代次数多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void PoseGraph2D::WaitForAllComputations () { int num_trajectory_nodes; { absl::MutexLock locker (&mutex_) ; num_trajectory_nodes = data_.num_trajectory_nodes; } const int num_finished_nodes_at_start = constraint_builder_.GetNumFinishedNodes (); auto report_progress = [this , num_trajectory_nodes, num_finished_nodes_at_start]() { if (num_trajectory_nodes != num_finished_nodes_at_start) { std::ostringstream progress_info; progress_info << "Optimizing: " << std::fixed << std::setprecision (1 ) << 100. * (constraint_builder_.GetNumFinishedNodes () - num_finished_nodes_at_start) / (num_trajectory_nodes - num_finished_nodes_at_start) << "%..." ; std::cout << "\r\x1b[K" << progress_info.str () << std::flush; } };
num_finished_nodes_at_start
表示此时已经优化的节点数,假设为 10
GetNumFinishedNodes
返回当前已经优化的节点数,假设为 11,也就是这个函数开始后,优化了1个节点
num_trajectory_nodes
,轨迹的总节点数
progress_info
输出的是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 { const auto predicate = [this ]() EXCLUSIVE_LOCKS_REQUIRED (work_queue_mutex_) { return work_queue_ == nullptr ; }; absl::MutexLock locker (&work_queue_mutex_) ; while (!work_queue_mutex_.AwaitWithTimeout ( absl::Condition (&predicate), absl::FromChrono (common::FromSeconds (1. )))) { report_progress (); } } absl::MutexLock locker (&mutex_) ; bool notification = false ; constraint_builder_.WhenDone ( [this , ¬ification](const constraints::ConstraintBuilder2D::Result& result) LOCKS_EXCLUDED (mutex_) { absl::MutexLock locker (&mutex_); data_.constraints.insert (data_.constraints.end (), result.begin (), result.end ()); notification = true ; }); const auto predicate = [¬ification]() EXCLUSIVE_LOCKS_REQUIRED (mutex_) { return notification; }; while (!mutex_.AwaitWithTimeout (absl::Condition (&predicate), absl::FromChrono (common::FromSeconds (1. )))) { report_progress (); } CHECK_EQ (constraint_builder_.GetNumFinishedNodes (), num_trajectory_nodes); std::cout << "\r\x1b[KOptimizing: Done. " << std::endl; }
就是把ceres的迭代次数设置为200,其他部分其实不用太深入研究了。