node_main.cc
中的Run
函数最后:1
2
3
4::ros::spin();
// 终止所有轨迹
node.FinishAllTrajectories();
node.RunFinalOptimization();
主要看FinishAllTrajectories
1
2
3
4
5
6
7
8
9
10
11
12void Node::FinishAllTrajectories()
{
carto::common::MutexLocker lock(&mutex_);
for (auto& entry : is_active_trajectory_) {
const int trajectory_id = entry.first;
// 已经lock了,所以叫做 FinishTrajectoryUnderLock
if (entry.second) {
CHECK_EQ(FinishTrajectoryUnderLock(trajectory_id).code,
cartographer_ros_msgs::StatusCode::OK);
}
}
}offline_node.cc
中还调用了一个Node::FinishTrajectory
(是这个函数唯一被调用的地方),还有就是finish_trajectory
服务的回调函数,以上3个函数实际都调用FinishTrajectoryUnderLock
1 | cartographer_ros_msgs::StatusResponse Node::FinishTrajectoryUnderLock( |
StatusResponse
不正常的code
是INVALID_ARGUMENT
, NOT_FOUND
, RESOURCE_EXHAUSTED
, 只有OK
是正常的
其中的关键函数就是:1
2
3
4
5
6
7
8
9
10
11
12
13
14void MapBuilderBridge::FinishTrajectory(const int trajectory_id)
{
LOG(INFO) << "Finishing trajectory with ID '" << trajectory_id << "'...";
// Make sure there is a trajectory with 'trajectory_id'.
CHECK_EQ(sensor_bridges_.count(trajectory_id), 1);
map_builder_->FinishTrajectory(trajectory_id);
sensor_bridges_.erase(trajectory_id);
}
// 再看这个函数
void MapBuilder::FinishTrajectory(const int trajectory_id) {
sensor_collator_->FinishTrajectory(trajectory_id);
pose_graph_->FinishTrajectory(trajectory_id);
}sensor_collator_
就是Collator::FinishTrajectory
或者 TrajectoryCollator::FinishTrajectory
,不用关注。
重要的是后端的同名函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14void PoseGraph2D::FinishTrajectory(const int trajectory_id)
{
AddWorkItem([this, trajectory_id]() LOCKS_EXCLUDED(mutex_)
{
absl::MutexLock locker(&mutex_);
CHECK(!IsTrajectoryFinished(trajectory_id)); // 不能是已结束
data_.trajectories_state[trajectory_id].state = TrajectoryState::FINISHED;
for (const auto& submap : data_.submap_data.trajectory(trajectory_id)) {
data_.submap_data.at(submap.id).state = SubmapState::kFinished;
}
return WorkItem::Result::kRunOptimization;
});
}
这里又是全局优化的标志kRunOptimization
,然后又去PoseGraph2D::HandleWorkQueue
,也是一次优化过程了