视觉SLAM十四讲学习6 Ceres Solver (1)入门
- 前言
- Hello World!
- 构建问题
- 求解设置
- 求解
- 完整代码
- 多维函数优化
前言
本篇开始学习SLAM的实际操作,从Ceres Solver开始。
Hello World!
构建问题
Ceres Solver是C++常用的非线性优化库。Ceres Solver解非线性优化的流程包含三步:构建优化问题,设置求解条件,求解。
考虑一个简单的最小二乘问题ceres求解:
min
1
2
∣
∣
10
−
x
∣
∣
2
\min \frac {1}{2} ||10-x||^2
min21∣∣10−x∣∣2
首先,在Ceres中构造一个代价函数,并重载()运算符:
struct LinearFunc {
template <typename T>
bool operater() (const T* const x, T* residual) const {
residual[0] = 10.0 - x[0];
return true;
}
}
其中,residual是最小二乘中的残差,x是迭代变量。
然后将代价函数添加到优化问题中:
double x = 5.0
ceres::CostFunction* cost_function = new AutoDiffCostFunction<LinearFunc, 1, 1>(new LinearFunc);
ceres::Problem problem;
problem.AddResidualBlock(cost_function, nullptr, &x)
其中,AutoDiffCostFunction将LinearFunc转换为ceres的自动求导类型(ceres可选数值求导,手动求导和自动求导三种类型),然后再添加到problem的残差块内。
求解设置
这里主要是选择求解器和求解结果的展示方式:
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
ceres::Summary summary;
这里,通过ceres::Solver::Options来进行求解器设置,比如线性求解器、非线性求解方法、线搜索方法等、求解结果打印等,并且通过ceres::Summary来获得求解中的情况。
求解
ceres::Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
最后通过ceres::Solver()来求解,std输出summary.BriefReport()得到优化过程的情况。
完整代码
#include "ceres/ceres.h"
struct CostFunctor
{
template <typename T>
bool operator()(const T* const x, T* residual) const {
residual[0] = 10.0 - x[0];
return true;
}
};
struct NumericCostFunctor{
template <typename T>
bool operator()(const T* const x, T* residual) const {
residual[0] = 10.0 - x[0];
return true;
}
};
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
double x_init = 5.;
double x = x_init;
ceres::Problem problem;
// ceres::CostFunction* cost_function = new ceres::AutoDiffCostFunction<CostFunctor, 1, 1>(new CostFunctor);
ceres::CostFunction* cost_function = new ceres::NumericDiffCostFunction<NumericCostFunctor, ceres::CENTRAL, 1, 1>(new NumericCostFunctor);
problem.AddResidualBlock(cost_function, nullptr, &x);
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
std::cout<<summary.BriefReport()<<"\n";
std::cout<<"x: "<< x_init << " -> " << x << " \n";
return 0;
}
多维函数优化
未完待续