Ceres solver 是谷歌开发的一款用于非线性优化的库,在谷歌的开源激光雷达slam项目cartographer中被大量使用。Ceres官网上的文档非常详细地介绍了其具体使用方法,相比于另外一个在slam中被广泛使用的图优化库G2O,ceres的文档可谓相当丰富详细(没有对比就没有伤害,主要是G2O资料太少了,对比起来就显得ceres的很多),下面我就介绍下如何使用ceres库进行简单的非线性优化,给各位ceres的初学者一个低门槛的入门教程,能比较直观地对使用ceres库求解优化问题的过程有一个清晰的了解。
简介
Ceres可以解决有界约束的线性最小二乘问题的形式
这种形式的问题出现在科学和工程的广泛领域——从统计学中的拟合曲线,到计算机视觉中的照片构建三维模型。在本章中,我们将学习如何使用ceres求解器求解。所有源码可以在这里下载:https://github.com/ceres-solver/ceres-solver
表达式:
为残差块(ResidualBlock),这里
为依赖参数块
的代价函数(CostFunction)。在大多数优化问题中,小群标量总是同时出现。例如,定义摄像机姿态的平移矢量的三个分量和四元数的四个分量。我们将这样一组小的标量称为参数块。当然,一个参数块可以只是一个参数。
和
是参数块
上的界限。
是一个损失函数(LossFunction),损失函数是一个标量函数,用于减少异常值对非线性最小二乘问题解的影响。
特别的当
,即为恒等函数,如果
和
我们得到了更熟悉的非线性最小二乘问题。
第一个例子(Hello World!)
首先,考虑寻找函数的最小值的问题
这是一个很小的问题。其最小值位于
。但这是一个很好的说明Ceres问题基础的例子。
第一步是构造一个函数去估计函数:
struct CostFunctor {
template <typename T>
bool operator()(const T* const x, T* residual) const {
residual[0] = T(10.0) - x[0];
return true;
}
};
值得注意的一件重要事情是, operator() 是一个模板化的方法,它假定所有的输入和输出是某种类型T的使用模板调用允许CeresCostFunctor::operator< T >()
,与T =double时剩余的价值是必要的,和一种特殊类型T =Jet,雅克比是必要的。在衍生品中,我们将更详细地讨论向谷神星提供衍生品的各种方法。
一旦我们有了计算残差的函数的方法,现在是时候构造一个非线性最小值了。平方问题,让Ceres来解决
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
// The variable to solve for with its initial value.
double initial_x = 5.0;
double x = initial_x;
// Build the problem.
Problem problem;
// Set up the only cost function (also known as residual). This uses
// auto-differentiation to obtain the derivative (jacobian).
CostFunction* cost_function =
new AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
problem.AddResidualBlock(cost_function, NULL, &x);
// Run the solver!
Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
std::cout << "x : " << initial_x
<< " -> " << x << "\n";
return 0;
}
自动求导函数将CostFunctor作为输入,自动微分它,并给它一个代价函数接口。
编译运行 examples/helloworld.cc 得到:
iter cost cost_change |gradient| |step| tr_ratio tr_radius ls_iter iter_time total_time
0 4.512500e+01 0.00e+00 9.50e+00 0.00e+00 0.00e+00 1.00e+04 0 5.33e-04 3.46e-03
1 4.511598e-07 4.51e+01 9.50e-04 9.50e+00 1.00e+00 3.00e+04 1 5.00e-04 4.05e-03
2 5.012552e-16 4.51e-07 3.17e-08 9.50e-04 1.00e+00 9.00e+04 1 1.60e-05 4.09e-03
Ceres Solver Report: Iterations: 2, Initial cost: 4.512500e+01, Final cost: 5.012552e-16, Termination: CONVERGENCE
x : 0.5 -> 10