研究SLAM,对编程的要求有多高?

2019 年 2 月 18 日 计算机视觉life

点击上方蓝字关注 计算机视觉life,置顶星标及时接收消息!

本文对 “研究SLAM,但编程又不好的人” 会有很大启发

研究SLAM的同学平时除了要看很多头疼的公式原理外,对编程也是有不少要求的。在学生阶段,很多同学都是用MATLAB作为主要编程语言,容易上手又简单。但是去看SLAM的开源代码,发现基本清一色都是C++,而且有不少开源代码使用C++到了出神入化的地步了。那么问题来了,学习SLAM是否可以不拘泥于编程语言的选择?到底对编程的要求有多高?

本文来自知乎上的同名问题,已经征得了部分答主的授权,对几个优秀回答进行了整理,如下

高翔

关于MATLAB

题主说MATLAB,主要原因是大多数人本科阶段接触的都是MATLAB,所以希望之后研究SLAM也用它。

MATLAB确实有很多优点:语法简单,开发速度快,调试方便,功能丰富。然而,在SLAM领域,MATLAB缺点也很明显,主要是这两个:

  • 需要正版软件(你不能实机上也装个盗版MATLAB吧);

  • 运行效率不高;

  • 需要一个巨大的安装包;

而相对的,C++的优势在于直接使用,有很高的运行效率,不过开发速度和调试方面慢于MATLAB。不过光运行效率这一条,就够许多SLAM方案选择C++作为开发语言了,因为运行效率真的很重要。同一个算法,拿MATLAB写出来实现不能实时,拿C++写的能实时,你说用哪个?

当然MATLAB也有一些用武之地。我见过一些SLAM相关的公开课程,让学生用MATLAB做仿真,交作业,这没有问题,比如SLAM toolbox 。同样的,比较类似于MATLAB的Python(以及octave)亦常被用于此道。它们在开发上的快捷带来了很多便利,当你想要验证一些数学理论、思想时,这些都是不错的工具。所谓技多不压身,题主掌握MATLAB和Python当然是很棒的。

但是一牵涉到实用,你会发现几乎所有的方案都在用C++。 因为运行效率实在是太重要了。

那既然有心思学MATLAB,为什么不学好C++呢?

C++需要掌握到什么程度?

接下来说说C++大概要学到什么程度。用程序员的话说,C++语言比较特殊,你可以说自己精通了Java,但千万不要说自己精通了C++。C++非常之博大精深,有数不清的特性,而且随着时间还会不断变化更新。不过,大多数人都用不着学会所有的C++特性,因为许多东西一辈子都用不到。

作为SLAM研究人员,我们面对的主要是算法层面的开发,所以更关心如何有效地实现各种相关的算法。而相对的,那些复杂的软件架构,设计模式,我个人认为在SLAM中倒是占次要地位的。毕竟您用SLAM的目的是计算一个位置以及建个地图,并不是要去写一套能够自动更新的、多人网上对战功能的机器人大战平台。您的主要精力可能会花在矩阵运算、分块、非线性优化的实现、图像处理上面;您可能对并发、指令集加速、GPU加速等话题感兴趣,也可以花点时间学习;你还可能想用模板来拓展你的算法,也不妨一试。相应的,很多功能性的东西,比如说UI、网络通信等等,当你用到的时候不妨接触一下,但专注于SLAM上时就不必专门去学习了。

话虽如此,SLAM所需的C++水平,大抵要高于你在书本上看到的那些个示例代码。因为那些代码是作者用来向初学者介绍语法的,所以会尽量简单。而实际见到的代码往往结合了各种奇特的技巧,乍看起来会显得高深莫测。比方说你在教科书里看的大概是这样:

int main int argc, char** argv )
{
    vector<string> vec;
    vec.push_back("abc");
    for ( int i=0; i<vec.size(); i++ )
    {
        // ...
    }
    return 0;
}

你看了C++ Primer Plus,觉得C++也不过如此,并没有啥特别难以理解的地方。然而实际代码大概是这样的:

嵌套的模板类(来自g2o的块求解器):

g2o::BlockSolver< g2o::BlockSolverTraits<3,1> >::LinearSolverType* linearSolver = new g2o::LinearSolverDense<g2o::BlockSolver< g2o::BlockSolverTraits<3,1> >::PoseMatrixType>(); 
g2o::BlockSolver< g2o::BlockSolverTraits<3,1> >* solver_ptr = new g2o::BlockSolver< g2o::BlockSolverTraits<3,1> >( linearSolver );    
g2o::OptimizationAlgorithmLevenberg* solver = new g2o::OptimizationAlgorithmLevenberg( solver_ptr );
g2o::SparseOptimizer optimizer;   
optimizer.setAlgorithm( solver );   

模板元(来自ceres的自动求导):

virtual bool Evaluate(double constconst* parameters,
                        double* residuals,
                        double** jacobians)
 const 
{
    if (!jacobians) {
      return internal::VariadicEvaluate<
          CostFunctor, double, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>
          ::Call(*functor_, parameters, residuals);
    }
    return internal::AutoDiff<CostFunctor, double,
           N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(
               *functor_,
               parameters,
               SizedCostFunction<kNumResiduals,
                                 N0, N1, N2, N3, N4,
                                 N5, N6, N7, N8, N9>::num_residuals(),
               residuals,
               jacobians);
}

C11新特性(来自SVO特征提取部分)

void Frame::setKeyPoints()
{
  for(size_t i = 0; i < 5; ++i)
    if(key_pts_[i] != NULL)
      if(key_pts_[i]->point == NULL)
        key_pts_[i] = NULL;

  std::for_each(fts_.begin(), fts_.end(), [&](Feature* ftr){ if(ftr->point != NULL) checkKeyPoints(ftr); });
}

谜之运算(来自SVO的深度滤波器):

void DepthFilter::updateSeed(const float x, const float tau2, Seed* seed)
{
  float norm_scale = sqrt(seed->sigma2 + tau2);
  if(std::isnan(norm_scale))
    return;
  boost::math::normal_distribution<float> nd(seed->mu, norm_scale);
  float s2 = 1./(1./seed->sigma2 + 1./tau2);
  float m = s2*(seed->mu/seed->sigma2 + x/tau2);
  float C1 = seed->a/(seed->a+seed->b) * boost::math::pdf(nd, x);
  float C2 = seed->b/(seed->a+seed->b) * 1./seed->z_range;
  float normalization_constant = C1 + C2;
  C1 /= normalization_constant;
  C2 /= normalization_constant;
  float f = C1*(seed->a+1.)/(seed->a+seed->b+1.) + C2*seed->a/(seed->a+seed->b+1.);
  float e = C1*(seed->a+1.)*(seed->a+2.)/((seed->a+seed->b+1.)*(seed->a+seed->b+2.))
          + C2*seed->a*(seed->a+1.0f)/((seed->a+seed->b+1.0f)*(seed->a+seed->b+2.0f));

  // update parameters
  float mu_new = C1*m+C2*seed->mu;
  seed->sigma2 = C1*(s2 + m*m) + C2*(seed->sigma2 + seed->mu*seed->mu) - mu_new*mu_new;
  seed->mu = mu_new;
  seed->a = (e-f)/(f-e/f);
  seed->b = seed->a*(1.0f-f)/f;
}

我不知道你们看到这些代码是什么心情,总之我当时内心的感受是:卧槽这怎么和教科书里的完全不一样啊!而且研究了半天发现人家居然是对的啊!

[我不是很擅长贴表情图总之你们脑补一下就好]

总而言之,对C++的水平要求应该是在教科书之上的。而且这个水平的提高,多数时候建立在你不断地看别人代码、码自己代码的过程之上。它是反复练习出来的,并不是仅仅通过看书就能领会的。特别是对于视觉SLAM问题,很多时候你没法照着论文把一套方案实现出来,这很大程度上取决于你的理论和代码功底。

所以,请尽早开始学习C++,尽早开始使用C++,才是研究SLAM的正确之道。不要长期彷徨在自己的舒适区里犹豫不决,这样是没有进步的。(同样的道理亦适用于想研究SLAM但不愿意学习Linux的朋友们)

Kache

我觉得对编程要求还是挺高的,先从后端说起吧
g2o, gtsam,ceres知道是肯定需要知道的,三者其实学习曲线都挺难的,你觉得你会用了是一回事,然后用好是一回事,自己写vertex, edge, factor, cost function又是另外一回事,如果你会写g2o里面的solver应该又是一个级别了吧。但是这三个在网上的资源而论g2o > ceres > gtsam。再者,你会调用api就代表你懂优化了吗,自己动手matlab写一下gauss-newton应该也可以试一试吧。当然,远古一点了levmar也很不错哦。直到这里,你确定你明白各种算法底层suitesparse里面的效率问题吗,如果挖掘到了这一层,还有各种线性代数库的比较哦,肯定是又快有慢。所以说,想要学会一到两个优化器不难,学会自定义有一点难,考虑到后端的效率自己写solver更难,深入到线性代数库的最底层,考虑问题结构,提升效率就更难了

前端,其实仅仅考虑点特征,也就那么多东西,V-SLAM用OPENCV也就够用了,而且opencv我觉得到API调用那一层也就足够了。如果考虑上RGBD,再加上一个PCL。理论知识方面基本的Multiview geometry其实也就足够了。但是前端的问题在于很多都是经验的东西,参数的选择,循环的次数等等。说白了我个人觉得视觉部分调参的问题更多,理论倒是不容易出问题。

前后段一起的话,什么线程管理就不用说了,该用的库都得上,例如boost啥的。有时候做visualization可能还需要一些别的库。

说完好像要求也就那样,反正我又不是CS出身活得还好好的

邵天兰

要搞SLAM,编程能力非常非常重要。编程能力就像运动员的力量和体能,是一切技巧和战术的基础。虽然研究的是算法,但良好的编程能力能够使你节省大量的时间,并且达到更好的效果。

根据我的经验,算法搞得特别好的人很少有编程不行的,因为编程好可以使你能够迅速验证想法。见过不少学生因为编程基础不好,在实现和debug上浪费大把大把的时间。这样的人当然很难把算法搞好。

这里编程能力有很多方面,以下简单说几个。赞多了再补( ̄▽ ̄)/

1. 阅读代码的能力
未说写,先说读。搞科研和搞工程都大忌闭门造车,除了paper外,开源代码是最有效的学习途径。一般而言,paper中只是着重描述比较创新的部分,80%以上的实现细节(甚至很多很关键的东西)需要从代码中了解。编程不好的人,往往也不太会读代码。

2. 架构软件,管理复杂项目的能力
一个SLAM方案通常由很多模块组成。我见过不少实验室的内部代码,一锅粥,学生们各种胡乱修补。这样必然导致效率低下。如果能做到模块化、低耦合,可以使开发事半功倍。

3. 高效实现的能力
过去八年间,我最少的一年也码了两万多行。。。根据我的体会,同样的算法,好的实现可以比不好的实现快2-10倍。复杂度越高越如是,例如3D  SLAM。要拥有高效实现的能力,必须熟悉常用的数据结构,对复杂度分析形成很好的直觉。

4. 管理多线程、异步程序的能力
SLAM往往涉及到多线程和异步程序,例如用于后端优化等。玩儿不转这个就会出现程序不稳定,或效率低。

Matlab不能满足需要。Matlab对数据结构的支持太差,而且速度慢。即使不考虑产品,只是做算法,也很不适合。自己做算法验证基本上就是C++或python,如果你因为不熟悉这些而选其他语言,会因为参考少、轮子少的原因效率很低。强烈建议题主学习C++。

推荐文章

从零开始一起学习SLAM | 为什么要学SLAM?
从零开始一起学习SLAM | 学习SLAM到底需要学什么?

从零开始一起学习SLAM | SLAM有什么用?

从零开始一起学习SLAM | C++新特性要不要学?

从零开始一起学习SLAM | 为什么要用齐次坐标?

从零开始一起学习SLAM | 三维空间刚体的旋转

从零开始一起学习SLAM | 为啥需要李群与李代数?

从零开始一起学习SLAM | 相机成像模型

从零开始一起学习SLAM | 不推公式,如何真正理解对极约束?

从零开始一起学习SLAM | 神奇的单应矩阵

从零开始一起学习SLAM | 你好,点云

从零开始一起学习SLAM | 给点云加个滤网

从零开始一起学习SLAM | 点云平滑法线估计

从零开始一起学习SLAM | 点云到网格的进化

从零开始一起学习SLAM | 理解图优化,一步步带你看懂g2o代码

SLAM初识

SLAM技术框架

惯性导航系统简介

视觉里程计:起源、优势、对比、应用

视觉里程计:特征点法之全面梳理

SLAM领域牛人、牛实验室、牛研究成果梳理

我用MATLAB撸了一个2D LiDAR SLAM

可视化理解四元数,愿你不再掉头发

IMU标定 | 工业界和学术界有什么不同?

汇总 | VIO、激光SLAM相关论文分类集锦

欢迎关注公众号:计算机视觉life,一起探索计算机视觉新世界~

点击阅读原文可以查看原文链接。

登录查看更多
24

相关内容

MATLAB 是 Matrix Laboratory 的缩写,是一款由美国 MathWorks 公司出品的商业数学软件。是一种适用于算法开发、数据可视化、数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simulink两大部分。
【开放书】SLAM 中的几何与学习方法,62页pdf
专知会员服务
107+阅读 · 2020年6月5日
Python导论,476页pdf,现代Python计算
专知会员服务
254+阅读 · 2020年5月17日
【经典书】数据结构与算法C++,第二版,738页pdf
专知会员服务
165+阅读 · 2020年3月27日
专知会员服务
84+阅读 · 2019年12月13日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
83+阅读 · 2019年11月25日
【书籍】深度学习框架:PyTorch入门与实践(附代码)
专知会员服务
160+阅读 · 2019年10月28日
SLAM中VIO的优势及入门姿势
计算机视觉life
86+阅读 · 2019年5月7日
语义信息与SLAM有哪些结合点?
计算机视觉life
5+阅读 · 2019年4月23日
高翔:谈谈语义SLAM/地图
计算机视觉life
32+阅读 · 2019年3月26日
【泡泡机器人】也来谈语义SLAM/语义地图
泡泡机器人SLAM
20+阅读 · 2019年3月12日
2018年SLAM、三维视觉方向求职经验分享
计算机视觉life
17+阅读 · 2019年2月25日
从零开始一起学习SLAM | 点云到网格的进化
计算机视觉life
12+阅读 · 2019年1月9日
从零开始一起学习SLAM | 学习SLAM到底需要学什么?
计算机视觉life
8+阅读 · 2018年9月9日
各编程领域最好的入门书籍
程序猿
27+阅读 · 2018年7月29日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
推荐|视觉SLAM漫淡:机器人即时定位与地图构建!
全球人工智能
8+阅读 · 2017年9月30日
Structure Aware SLAM using Quadrics and Planes
Arxiv
4+阅读 · 2018年8月13日
Arxiv
6+阅读 · 2018年3月29日
Arxiv
6+阅读 · 2018年1月14日
VIP会员
相关VIP内容
【开放书】SLAM 中的几何与学习方法,62页pdf
专知会员服务
107+阅读 · 2020年6月5日
Python导论,476页pdf,现代Python计算
专知会员服务
254+阅读 · 2020年5月17日
【经典书】数据结构与算法C++,第二版,738页pdf
专知会员服务
165+阅读 · 2020年3月27日
专知会员服务
84+阅读 · 2019年12月13日
【电子书】C++ Primer Plus 第6版,附PDF
专知会员服务
83+阅读 · 2019年11月25日
【书籍】深度学习框架:PyTorch入门与实践(附代码)
专知会员服务
160+阅读 · 2019年10月28日
相关资讯
SLAM中VIO的优势及入门姿势
计算机视觉life
86+阅读 · 2019年5月7日
语义信息与SLAM有哪些结合点?
计算机视觉life
5+阅读 · 2019年4月23日
高翔:谈谈语义SLAM/地图
计算机视觉life
32+阅读 · 2019年3月26日
【泡泡机器人】也来谈语义SLAM/语义地图
泡泡机器人SLAM
20+阅读 · 2019年3月12日
2018年SLAM、三维视觉方向求职经验分享
计算机视觉life
17+阅读 · 2019年2月25日
从零开始一起学习SLAM | 点云到网格的进化
计算机视觉life
12+阅读 · 2019年1月9日
从零开始一起学习SLAM | 学习SLAM到底需要学什么?
计算机视觉life
8+阅读 · 2018年9月9日
各编程领域最好的入门书籍
程序猿
27+阅读 · 2018年7月29日
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
推荐|视觉SLAM漫淡:机器人即时定位与地图构建!
全球人工智能
8+阅读 · 2017年9月30日
Top
微信扫码咨询专知VIP会员