优化的具体实现在优化器optimization_problem_
。将优化的结果采用回调的方式,返回到result中。
后端将数据加入到 optimization_problem_
的对应传感器队列中,并按时间排列。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21void PoseGraph2D::HandleWorkQueue(
const constraints::ConstraintBuilder2D::Result& result)
{
{ // 将新的约束添加到全局约束队列中
absl::MutexLock locker(&mutex_);
data_.constraints.insert(data_.constraints.end(), result.begin(),
result.end() );
}
// ceres 在这里
RunOptimization();
// 以下是 省略 的内容
//如果设置了全局优化回调函数,则进行调用
//根据约束结果,更新轨迹间的链接关系
// 优化完成后,累计节点清零
// 计算相同轨迹的 inter_constraints_same_trajectory
// 计算不同轨迹的 inter_constraints_different_trajectory
// 优化结束后,重新开启任务队列,即继续执行
// work_queue_里的 work_item
DrainWorkQueue();
}
RunOptimization
优化的实际就是成员变量node_data_
和 submap_data_
,也就是1
2
3
4
5
6
7
8
9
10
11
12struct NodeSpec2D
{
common::Time time;
transform::Rigid2d local_pose_2d;
transform::Rigid2d global_pose_2d;
Eigen::Quaterniond gravity_alignment;
};
struct SubmapSpec2D
{
transform::Rigid2d global_pose;
};
1 | void PoseGraph2D::RunOptimization() |
将所有内部约束和外部约束合并在一起执行Solve
遍历所有submap,建立参数块;遍历所有node,建立参数块。
根据约束,添加残差函数;
处理里程计问题,添加可能的残差;
求解返回结果;
1 | absl::MutexLock locker(&mutex_); |
优化并非是实时,是在后台进行运行的,并且需要一定的时间。因此当完成优化时,前端输出结果已经对整个位姿图个数进行了增加。后面新加入的节点并未优化,所以返回优化的结果没有最新加入轨迹节点对应的结果。因此采用优化后结果中最后一个轨迹节点的位姿的转移矩阵,作为未参与优化轨迹节点的转移矩阵进行更新。
其中 为参与优化的节点,优化前位姿为 ,优化后的位姿为 。而 则为未参与优化的节点。