SLAM本质剖析-Ceres

简介: SLAM本质剖析-Ceres

0. 前言


在了解SLAM的原理、流程后,个人经常实时困惑该如何去从零开始去设计编写一套能够符合我们需求的SLAM框架。作者认为Ceres、Eigen、Sophus、G2O这几个函数库无法避免,尤其是Ceres函数库在激光SLAM和V-SLAM的优化中均有着大量的应用。所以作者从Ceres作为开端,来对手写SLAM开个头,来方便各位后续的开发。


这里分享以为博主写的博客,个人看了感觉写的不错,对SLAM的剖析很细致


1.Ceres示例


首先我们需要明确Ceres函数库在SLAM中主要起到的作用是优化。目前Bundle Adjustment 其本质还是离不开最小二乘原理(几乎所有优化问题其本质都是最小二乘),目前Bundle Adjustment 优化框架最为代表的是Ceres solver和G2O(这里主要介绍ceres solver)。Ceres中的优化需要四步,构建优化的残差函数,构建优化问题,在每次获取到数据后添加残差块,总体优化。


构建残差函数:


//构建代价函数结构体,residual为残差。
//last_point_a_为这一帧中的点a,curr_point_b_为点a旋转后和上一帧里最近的点
//curr_point_c_为点b同线或上线号的点,curr_point_d_为点b下线号的点
//b,c,d与a点距离不超过3m
//plane_norm为根据向量bc和bd求出的法向量
struct CURVE_FITTING_COST
{
  //类似构造函数
  CURVE_FITTING_COST(Eigen::Vector3d _curr_point_a_, Eigen::Vector3d _last_point_b_,
       Eigen::Vector3d _last_point_c_, Eigen::Vector3d _last_point_d_):
       curr_point_a_(_curr_point_a_),last_point_b_(_last_point_b_),
       last_point_c_(_last_point_c_),last_point_d_(_last_point_d_)
  {
     plane_norm = (last_point_d_ - last_point_b_).cross(last_point_c_ - last_point_b_);
     plane_norm.normalize();
  }
  template <typename T>
  //plane_norm点乘向量ab为a点距面bcd的距离,即残差
  bool operator()(const T* q,const T* t,T* residual)const
  {
    Eigen::Matrix<T, 3, 1> p_a_curr{T(curr_point_a_.x()), T(curr_point_a_.y()), T(curr_point_a_.z())};
    Eigen::Matrix<T, 3, 1> p_b_last{T(last_point_b_.x()), T(last_point_b_.y()), T(last_point_b_.z())};
    Eigen::Quaternion<T> rot_q{q[3], q[0], q[1], q[2]};
    Eigen::Matrix<T, 3, 1> rot_t{t[0], t[1], t[2]};
    Eigen::Matrix<T, 3, 1> p_a_last;
    p_a_last=rot_q * p_a_curr + rot_t;
    residual[0]=abs((p_a_last - p_b_last).dot(plane_norm));
    return true;
  }
  const Eigen::Vector3d curr_point_a_,last_point_b_,last_point_c_,last_point_d_;
  Eigen::Vector3d plane_norm;
};


20200801115913834.gif


构建优化问题:


//优化问题构建
ceres::LossFunction *loss_function = new ceres::HuberLoss(0.1);
ceres::LocalParameterization *q_parameterization =
new ceres::EigenQuaternionParameterization();
ceres::Problem::Options problem_options;
ceres::Problem problem(problem_options);
problem.AddParameterBlock(para_q, 4, q_parameterization);
problem.AddParameterBlock(para_t, 3);


每次求出abcd点后,将他们的坐标构建成Eigen::Vector3d数据,添加残差块:


Eigen::Vector3d curr_point_a(laserCloudIn_plane.points[i].x,
       laserCloudIn_plane.points[i].y,
       laserCloudIn_plane.points[i].z);
Eigen::Vector3d last_point_b(laserCloudIn_plane_last.points[closestPointInd].x,laserCloudIn_plane_last.points[closestPointInd].y,
       laserCloudIn_plane_last.points[closestPointInd].z);
Eigen::Vector3d last_point_c(laserCloudIn_plane_last.points[minPointInd2].x,
       laserCloudIn_plane_last.points[minPointInd2].y,
       laserCloudIn_plane_last.points[minPointInd2].z);
Eigen::Vector3d last_point_d(laserCloudIn_plane_last.points[minPointInd3].x,
       laserCloudIn_plane_last.points[minPointInd3].y,
       laserCloudIn_plane_last.points[minPointInd3].z);
problem.AddResidualBlock(new ceres::AutoDiffCostFunction<CURVE_FITTING_COST,1,4,3>
    (new CURVE_FITTING_COST(last_point_a,curr_point_b,
     curr_point_c,curr_point_d)),loss_function,para_q,para_t);


遍历过所有的a点后,就可以优化求解了。


//所有前一帧里的点都当a点遍历过后,进行优化
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
//迭代数
options.max_num_iterations = 5;
//进度是否发到STDOUT
options.minimizer_progress_to_stdout = false;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);


而在V-SLAM中Ceres则用的更多,我们可以看下下面的例子


7c20e788a992488cb2361b95cd06e51b.png

相关文章
|
传感器 机器学习/深度学习 人工智能
苏黎世理工最新!maplab2.0:模块化的多模态建图定位框架
将多传感器模态和深度学习集成到同时定位和mapping(SLAM)系统中是当前研究的重要领域。多模态是在具有挑战性的环境中实现鲁棒性和具有不同传感器设置的异构多机器人系统的互操作性的一块垫脚石。借助maplab 2.0,这个多功能的开源平台,可帮助开发、测试新模块和功能,并将其集成到一个成熟的SLAM系统中。
苏黎世理工最新!maplab2.0:模块化的多模态建图定位框架
|
1月前
|
机器学习/深度学习 人工智能 算法
从数据增强的隐藏作用出发,揭示视觉强化学习可塑性损失的独特机制
【10月更文挑战第22天】视觉强化学习(VRL)通过智能体与环境的交互学习最优策略,但可塑性损失是其关键挑战。近期一篇论文《Revisiting Plasticity in Visual Reinforcement Learning: Data, Modules and Training Stages》通过实证研究,揭示了数据增强、评论家可塑性损失及早期干预在维持智能体可塑性方面的作用,并提出了一种动态调整重放率的方法,为解决高重放率困境提供了新思路。
46 2
|
5月前
|
存储 安全 程序员
【C++11】C++11深度解剖(上)
【C++11】C++11深度解剖(上)
41 0
|
5月前
|
存储 算法 编译器
【C++11】C++11深度解剖(下)
【C++11】C++11深度解剖(下)
44 0
|
7月前
|
机器学习/深度学习 自然语言处理 运维
深度探索变分自编码器:理论与应用代码之韵:探索编程艺术的无限可能
【5月更文挑战第31天】 在深度学习的众多架构中,变分自编码器(Variational Autoencoder, VAE)以其对数据生成和潜在空间建模的强大能力而脱颖而出。本文将深入探讨VAE的核心原理,包括其概率生成模型、变分推断以及重参数化技巧,并剖析其在多个领域的实际应用案例。通过细致的技术解析与实例演示,我们旨在为读者提供一个关于VAE的全面视角,同时探讨当前的研究动态及未来发展趋势。
|
计算机视觉
UniMatch项目原作解读:统一光流、立体匹配和深度估计三个任务
UniMatch项目原作解读:统一光流、立体匹配和深度估计三个任务
181 0
|
机器学习/深度学习 算法 计算机视觉
|
机器学习/深度学习 传感器 存储
2022最新!视觉SLAM综述(多传感器/姿态估计/动态环境/视觉里程计)(下)
论文调查的主要目的是介绍VSLAM系统的最新进展,并讨论现有的挑战和未来趋势。论文对在VSLAM领域发表的45篇有影响力的论文进行了深入的调查,并根据不同的特点对这些方法进行了分类,包括novelty domain、目标、采用的算法和语义水平。最后论文讨论了当前的趋势和未来的方向,有助于研究人员进行研究。
2022最新!视觉SLAM综述(多传感器/姿态估计/动态环境/视觉里程计)(下)
|
传感器 机器学习/深度学习 数据采集
2022最新!视觉SLAM综述(多传感器/姿态估计/动态环境/视觉里程计)(上)
论文调查的主要目的是介绍VSLAM系统的最新进展,并讨论现有的挑战和未来趋势。论文对在VSLAM领域发表的45篇有影响力的论文进行了深入的调查,并根据不同的特点对这些方法进行了分类,包括novelty domain、目标、采用的算法和语义水平。最后论文讨论了当前的趋势和未来的方向,有助于研究人员进行研究。
2022最新!视觉SLAM综述(多传感器/姿态估计/动态环境/视觉里程计)(上)
|
传感器 存储 编解码
Loam算法详解(配合开源代码aloam)
Loam算法详解(配合开源代码aloam)
801 0
Loam算法详解(配合开源代码aloam)