当前位置: 首页 > article >正文

SLAM--ceres solver

Catalogue

  • Curve fitting
  • Bundle Adjustment
  • Reference

Compared to g2o, Ceres Solver has more adequate and complete tutorials including introductory tutorials and bunch of examples of “Bundle Adjustment” for SLAM. In addition, the efficiency of Ceres slightly exceeds that of g2o. Thus, it is possible to deploy Ceres Solver in your projects related to SLAM.

Curve fitting

This example is selected from the tutorial, which is a simple optimization problem and can clearly present the frame.

To start with, we need to define a templated object to evaluate the residual.

struct ExponentialResidual {
  ExponentialResidual(double x, double y)
      : x_(x), y_(y) {}

  template <typename T>
  bool operator()(const T* const m, const T* const c, T* residual) const {
    residual[0] = y_ - exp(m[0] * x_ + c[0]);
    return true;
  }

 private:
  // Observations for a sample.
  const double x_;
  const double y_;
};

The observations are a 2 n 2n 2n data array. Then, we can construct the problem and use AutoDiffCostFunction to differentiate automatically.

// Initiate the parameters.
double m = 0.0;
double c = 0.0;
//ceres::Problem
Problem problem;

for (int i = 0; i < kNumObservations; ++i) {
  CostFunction* cost_function =
       new AutoDiffCostFunction<ExponentialResidual, 1, 1, 1>(
           new ExponentialResidual(data[2 * i], data[2 * i + 1]));
  // Add every observation's residual to problem.
  problem.AddResidualBlock(cost_function, nullptr, &m, &c);
}

Solve the problem:

  //Set the solver's options.
  Solver::Options options;
  options.max_num_iterations = 25;
  options.linear_solver_type = ceres::DENSE_QR;
  options.minimizer_progress_to_stdout = true;

  Solver::Summary summary;
  Solve(options, &problem, &summary);

 

Bundle Adjustment

The structure :

struct SnavelyReprojectionError {
  SnavelyReprojectionError(double observed_x, double observed_y)
      : observed_x(observed_x), observed_y(observed_y) {}

  template <typename T>
  bool operator()(const T* const camera,
                  const T* const point,
                  T* residuals) const {
    // camera[0,1,2] are the angle-axis rotation.
    T p[3];
    ceres::AngleAxisRotatePoint(camera, point, p);
    // camera[3,4,5] are the translation.
    p[0] += camera[3]; p[1] += camera[4]; p[2] += camera[5];

    // Compute the center of distortion. The sign change comes from
    // the camera model that Noah Snavely's Bundler assumes, whereby
    // the camera coordinate system has a negative z axis.
    T xp = - p[0] / p[2];
    T yp = - p[1] / p[2];

    // Apply second and fourth order radial distortion.
    const T& l1 = camera[7];
    const T& l2 = camera[8];
    T r2 = xp*xp + yp*yp;
    T distortion = 1.0 + r2  * (l1 + l2  * r2);

    // Compute final projected point position.
    const T& focal = camera[6];
    T predicted_x = focal * distortion * xp;
    T predicted_y = focal * distortion * yp;

    // The error is the difference between the predicted and observed position.
    residuals[0] = predicted_x - T(observed_x);
    residuals[1] = predicted_y - T(observed_y);
    return true;
  }

   // Factory to hide the construction of the CostFunction object from
   // the client code.
   static ceres::CostFunction* Create(const double observed_x,
                                      const double observed_y) {
     return (new ceres::AutoDiffCostFunction<SnavelyReprojectionError, 2, 9, 3>(
                 new SnavelyReprojectionError(observed_x, observed_y)));
   }

  double observed_x;
  double observed_y;
};

Construct bundle adjustment problem:

ceres::Problem problem;
for (int i = 0; i < bal_problem.num_observations(); ++i) {
  ceres::CostFunction* cost_function =
      SnavelyReprojectionError::Create(
           bal_problem.observations()[2 * i + 0],
           bal_problem.observations()[2 * i + 1]);
  problem.AddResidualBlock(cost_function,
                           nullptr /* squared loss */,
                           bal_problem.mutable_camera_for_observation(i),
                           bal_problem.mutable_point_for_observation(i));
}

Optimization:

ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_SCHUR;
options.minimizer_progress_to_stdout = true;
ceres::Solver::Summary summary;

Reference

http://ceres-solver.org/nnls_tutorial.html


http://www.kler.cn/a/13904.html

相关文章:

  • 【面试】你在项目中遇到过慢查询问题吗?你是怎么做SQL优化的?
  • 基于Java+Springboot+Vue+elememt美食论坛平台设计实现
  • 17.Java枚举(Enum)
  • 知识变现海哥|研究了100个项目,这个才是人生逆袭首选
  • 运筹说 第94期|论文速读之基于关键路径的置换流水车间调度问题
  • Qt音视频开发40-ffmpeg采集桌面并录制
  • 26岁转行网络安全,成功上岸安全开发!
  • tem_get-获得1688商品详情 1688.API接口接入
  • 初始VUE
  • 在一家IT公司工作了五六年,想跳槽又感到有压力怎么办?
  • Java基础(十二)Java比较器
  • Android 层和屏幕
  • 【测试面试】你要的宝典,软件接口测试面试题大全(总结)--附答案
  • 脉诊在现代医学中的应用与局限性
  • 4月19号软件更新资讯合集....
  • 条码控件Aspose.BarCode入门教程(8):C#从图像中读取条形码
  • Android12 人脸解锁如何默认打开活体检测功能
  • GPT模型支持下的Python-GEE遥感云大数据分析、管理与可视化技术及多领域案例实践
  • 让人悲观的国内ChatGPT的未来
  • IS220UCSAH1A利用电子和空穴两种载流子导电的,所以叫做双极型电路