你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

视觉SLAM十四讲学习6 Ceres Solver (1) 入门

2021/12/30 21:24:40

视觉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 min2110x2
首先,在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;
}

多维函数优化

未完待续