Refactor calling optimization into DispatchOptimization. (#729)
I noticed that @jihoonl opened the PR #726 which performs a similar thing. As discussed in googlecartographer/cartographer_ros#613 (@cschuet has already taken a look), I pulled this out of #481 (a really old PR whose merging has been postponed), which is an example where re-running optimization is triggered from elsewhere as well (besides from `ComputeConstraintsForNode`). This refactoring makes libcartographer friendlier for use cases such as that one. An important detail is that I have changed the condition in `WaitForAllComputations` to also check if the work queue is empty. If there are other things on the worker queue besides `ComputeConstraintsForNode`, currently we will wrongfully conclude that all computations are done. (This detail was merged in #754, so it's no longer in the diff of this PR). Also missing is the same thing for 3D. I can add that when we settle on this. Also, I suggest that `run_loop_closure` gets renamed to `run_optimization`.master
parent
923d643b86
commit
58d94aaa68
|
@ -269,9 +269,14 @@ void PoseGraph::ComputeConstraintsForNode(
|
||||||
}
|
}
|
||||||
constraint_builder_.NotifyEndOfNode();
|
constraint_builder_.NotifyEndOfNode();
|
||||||
++num_nodes_since_last_loop_closure_;
|
++num_nodes_since_last_loop_closure_;
|
||||||
|
CHECK(!run_loop_closure_);
|
||||||
if (options_.optimize_every_n_nodes() > 0 &&
|
if (options_.optimize_every_n_nodes() > 0 &&
|
||||||
num_nodes_since_last_loop_closure_ > options_.optimize_every_n_nodes()) {
|
num_nodes_since_last_loop_closure_ > options_.optimize_every_n_nodes()) {
|
||||||
CHECK(!run_loop_closure_);
|
DispatchOptimization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoseGraph::DispatchOptimization() {
|
||||||
run_loop_closure_ = true;
|
run_loop_closure_ = true;
|
||||||
// If there is a 'work_queue_' already, some other thread will take care.
|
// If there is a 'work_queue_' already, some other thread will take care.
|
||||||
if (work_queue_ == nullptr) {
|
if (work_queue_ == nullptr) {
|
||||||
|
@ -279,8 +284,6 @@ void PoseGraph::ComputeConstraintsForNode(
|
||||||
HandleWorkQueue();
|
HandleWorkQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
common::Time PoseGraph::GetLatestNodeTime(
|
common::Time PoseGraph::GetLatestNodeTime(
|
||||||
const mapping::NodeId& node_id, const mapping::SubmapId& submap_id) const {
|
const mapping::NodeId& node_id, const mapping::SubmapId& submap_id) const {
|
||||||
common::Time time = trajectory_nodes_.at(node_id).constant_data->time;
|
common::Time time = trajectory_nodes_.at(node_id).constant_data->time;
|
||||||
|
@ -384,8 +387,8 @@ void PoseGraph::FinishTrajectory(const int trajectory_id) {
|
||||||
for (const auto& submap : submap_data_.trajectory(trajectory_id)) {
|
for (const auto& submap : submap_data_.trajectory(trajectory_id)) {
|
||||||
submap_data_.at(submap.id).state = SubmapState::kFinished;
|
submap_data_.at(submap.id).state = SubmapState::kFinished;
|
||||||
}
|
}
|
||||||
// TODO(jihoonl): Refactor HandleWorkQueue() logic from
|
CHECK(!run_loop_closure_);
|
||||||
// ComputeConstraintsForNode and call from here
|
DispatchOptimization();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,14 +508,21 @@ void PoseGraph::AddTrimmer(std::unique_ptr<mapping::PoseGraphTrimmer> trimmer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseGraph::RunFinalOptimization() {
|
void PoseGraph::RunFinalOptimization() {
|
||||||
WaitForAllComputations();
|
{
|
||||||
|
common::MutexLocker locker(&mutex_);
|
||||||
|
AddWorkItem([this]() REQUIRES(mutex_) {
|
||||||
optimization_problem_.SetMaxNumIterations(
|
optimization_problem_.SetMaxNumIterations(
|
||||||
options_.max_num_final_iterations());
|
options_.max_num_final_iterations());
|
||||||
RunOptimization();
|
DispatchOptimization();
|
||||||
|
});
|
||||||
|
AddWorkItem([this]() REQUIRES(mutex_) {
|
||||||
optimization_problem_.SetMaxNumIterations(
|
optimization_problem_.SetMaxNumIterations(
|
||||||
options_.optimization_problem_options()
|
options_.optimization_problem_options()
|
||||||
.ceres_solver_options()
|
.ceres_solver_options()
|
||||||
.max_num_iterations());
|
.max_num_iterations());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
WaitForAllComputations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseGraph::RunOptimization() {
|
void PoseGraph::RunOptimization() {
|
||||||
|
|
|
@ -215,6 +215,9 @@ class PoseGraph : public mapping::PoseGraph {
|
||||||
// Whether the optimization has to be run before more data is added.
|
// Whether the optimization has to be run before more data is added.
|
||||||
bool run_loop_closure_ GUARDED_BY(mutex_) = false;
|
bool run_loop_closure_ GUARDED_BY(mutex_) = false;
|
||||||
|
|
||||||
|
// Schedules optimization (i.e. loop closure) to run.
|
||||||
|
void DispatchOptimization() REQUIRES(mutex_);
|
||||||
|
|
||||||
// Current optimization problem.
|
// Current optimization problem.
|
||||||
pose_graph::OptimizationProblem optimization_problem_;
|
pose_graph::OptimizationProblem optimization_problem_;
|
||||||
pose_graph::ConstraintBuilder constraint_builder_ GUARDED_BY(mutex_);
|
pose_graph::ConstraintBuilder constraint_builder_ GUARDED_BY(mutex_);
|
||||||
|
|
|
@ -286,9 +286,14 @@ void PoseGraph::ComputeConstraintsForNode(
|
||||||
}
|
}
|
||||||
constraint_builder_.NotifyEndOfNode();
|
constraint_builder_.NotifyEndOfNode();
|
||||||
++num_nodes_since_last_loop_closure_;
|
++num_nodes_since_last_loop_closure_;
|
||||||
|
CHECK(!run_loop_closure_);
|
||||||
if (options_.optimize_every_n_nodes() > 0 &&
|
if (options_.optimize_every_n_nodes() > 0 &&
|
||||||
num_nodes_since_last_loop_closure_ > options_.optimize_every_n_nodes()) {
|
num_nodes_since_last_loop_closure_ > options_.optimize_every_n_nodes()) {
|
||||||
CHECK(!run_loop_closure_);
|
DispatchOptimization();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PoseGraph::DispatchOptimization() {
|
||||||
run_loop_closure_ = true;
|
run_loop_closure_ = true;
|
||||||
// If there is a 'work_queue_' already, some other thread will take care.
|
// If there is a 'work_queue_' already, some other thread will take care.
|
||||||
if (work_queue_ == nullptr) {
|
if (work_queue_ == nullptr) {
|
||||||
|
@ -296,7 +301,6 @@ void PoseGraph::ComputeConstraintsForNode(
|
||||||
HandleWorkQueue();
|
HandleWorkQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
common::Time PoseGraph::GetLatestNodeTime(
|
common::Time PoseGraph::GetLatestNodeTime(
|
||||||
const mapping::NodeId& node_id, const mapping::SubmapId& submap_id) const {
|
const mapping::NodeId& node_id, const mapping::SubmapId& submap_id) const {
|
||||||
|
@ -401,8 +405,8 @@ void PoseGraph::FinishTrajectory(const int trajectory_id) {
|
||||||
for (const auto& submap : submap_data_.trajectory(trajectory_id)) {
|
for (const auto& submap : submap_data_.trajectory(trajectory_id)) {
|
||||||
submap_data_.at(submap.id).state = SubmapState::kFinished;
|
submap_data_.at(submap.id).state = SubmapState::kFinished;
|
||||||
}
|
}
|
||||||
// TODO(jihoonl): Refactor HandleWorkQueue() logic from
|
CHECK(!run_loop_closure_);
|
||||||
// ComputeConstraintsForNode and call from here
|
DispatchOptimization();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,14 +511,21 @@ void PoseGraph::AddTrimmer(std::unique_ptr<mapping::PoseGraphTrimmer> trimmer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseGraph::RunFinalOptimization() {
|
void PoseGraph::RunFinalOptimization() {
|
||||||
WaitForAllComputations();
|
{
|
||||||
|
common::MutexLocker locker(&mutex_);
|
||||||
|
AddWorkItem([this]() REQUIRES(mutex_) {
|
||||||
optimization_problem_.SetMaxNumIterations(
|
optimization_problem_.SetMaxNumIterations(
|
||||||
options_.max_num_final_iterations());
|
options_.max_num_final_iterations());
|
||||||
RunOptimization();
|
DispatchOptimization();
|
||||||
|
});
|
||||||
|
AddWorkItem([this]() REQUIRES(mutex_) {
|
||||||
optimization_problem_.SetMaxNumIterations(
|
optimization_problem_.SetMaxNumIterations(
|
||||||
options_.optimization_problem_options()
|
options_.optimization_problem_options()
|
||||||
.ceres_solver_options()
|
.ceres_solver_options()
|
||||||
.max_num_iterations());
|
.max_num_iterations());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
WaitForAllComputations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PoseGraph::LogResidualHistograms() {
|
void PoseGraph::LogResidualHistograms() {
|
||||||
|
|
|
@ -219,6 +219,9 @@ class PoseGraph : public mapping::PoseGraph {
|
||||||
// Whether the optimization has to be run before more data is added.
|
// Whether the optimization has to be run before more data is added.
|
||||||
bool run_loop_closure_ GUARDED_BY(mutex_) = false;
|
bool run_loop_closure_ GUARDED_BY(mutex_) = false;
|
||||||
|
|
||||||
|
// Schedules optimization (i.e. loop closure) to run.
|
||||||
|
void DispatchOptimization() REQUIRES(mutex_);
|
||||||
|
|
||||||
// Current optimization problem.
|
// Current optimization problem.
|
||||||
pose_graph::OptimizationProblem optimization_problem_;
|
pose_graph::OptimizationProblem optimization_problem_;
|
||||||
pose_graph::ConstraintBuilder constraint_builder_ GUARDED_BY(mutex_);
|
pose_graph::ConstraintBuilder constraint_builder_ GUARDED_BY(mutex_);
|
||||||
|
|
Loading…
Reference in New Issue