点击上方“3D视觉工坊”,选择“星标”
干货第一时间送达
https://www.zhihu.com/question/51707998/answer/1263706761
本文仅作为学术分享,如果有侵权,会删文处理
研究SLAM,对编程的要求有多高?
作者:岑斌
https://www.zhihu.com/question/51707998/answer/1263706761
作为不知名slam从业者,狗刨江湖6年,回答一波。
本人技术差强人意,经验倒是累计不少,权当跟题主分享一下个人感受和看法吧。
题主问slam对编程的要求有多高。
大概有两三层楼那么高吧。(开篇先皮一下就很开心)
slam编程个人认为主要分两方面,基本技术和综合素质。
拿绘画做比方,首先都是先要提升技巧熟练度和色彩敏感度,成为一个合格的绘画技工。在这个过程中不断提高个人审美度,知道什么是美,什么是不美,形成自己的风格后,就进化成了艺术家。(手动狗头护身)
先说slam编程要求中的基本技术:
1、Matlab\c\c++
说来惭愧,我现在还在用matlab写的代码跑一些离线的数据来调试和验证。
跑一些轻量的算法代码还挺好用的。
gui之类的插件啊,plot做图形显示在ppt用来展示说明啊等等,反正就是当个工具来用。
如果真的用matlab跑offline slam,2015年的时候我试过,10米轨迹采集的数据,跑了16个小时...头都是晕的,没法实际调试。
毕竟matlab全称就是矩阵实验室嘛,理论和工程还是有差距的,最直接的体现就是效率上。
所以编程语言主力还是c\c++,不论是效率还是环境,在嵌入式端实时跑slam,毋庸置疑是不二选择。
我一直认为编程语言只是一件用来辅助工程师实现需求的工具箱。
尤其是c\c++,里面的工具琳琅满目,目不暇接,接天莲叶无穷碧。
要一口气吃饱,把所有技术都运用得融会贯通显然不切实际,也没有必要。
用工程化的术语来说,就是投入和产出比非常低下。
你可以在手边常备一本当作工具书,对大体的技术框架很了解(其实就是对目录烂熟于心),到时候遇到问题,边学边用即可。
手艺活嘛,贵在坚持,日积月累,自然而然,水到渠成,臻于化境。
2、通读经典源码
slam编程其实很容易入门。因为有非常多好的开源代码免费给你看。
就好比少林寺的易筋经某天突然在路边摊就可以用五毛钱买到的感觉,真的是血赚。
只是好东西不是每个人都能够消化的,有些好书也不一定就很好读。
要有耐心和毅力,仔仔细细、里里外外看几遍,受益匪浅。
当然这个很花时间,我有工作压力,一般挑着看部分算法的代码实现就完事儿了。
3、Google
这个懂的都懂。如果没有goole和GitHub,我的编程生涯是不完整的(狗头)
4、各种成熟的配套库和工具
ros, eigen, opencv, g2o, ceres, PCL等等,也是当工具使唤,先是拿来主义,后面再慢慢转化成自己的东西。
再说slam编程中的综合素质。
基本技巧可以让你守住饭碗,那么综合素质则是让你超凡脱俗的存在。
以下内容,题主信则有,不信就当听个说书。
1、逻辑能力
如果研究slam是练武修真的话,那么逻辑能力一定是里面最具杀力的剑术!
清晰的思维,缜密的逻辑,可以帮助你斩断乱麻,集中火力,直达本质,让自己的slam更上一层楼。
一样的算法,别人耗时不少,效果一般,你有出众的思维逻辑能力,优化代码后,可以做到耗时更短,效果更佳!
出现问题,经过数据分析,合理推断,能够更加快速的定位源头,解决问题。
2、数学功底
如果思维逻辑是剑术,那么数学就是内力。
降龙十八掌谁都知道厉害吧,但是如果没有内力支持,就只是一个花架子的拳脚功夫。
对slam来说,窃以为最重要的数学有两门,其一是线性代数,其二是概率论。
下限要求很低,目前主流的公式,直接拿来主义。
上限无限高,具体公式的推导和调整,包括有些magicvalue,不懂就是玄学,搞懂了用起来可以达到另一个境界。
以上就是我这个狗刨slam江湖六年的不知名小游侠的经验之谈。
做不了天上来地上飞的神仙大侠,起码也能在江湖里混口饭吃。
作者:半闲居士
https://www.zhihu.com/question/51707998/answer/127192245
大多数人本科阶段接触的都是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++语言比较特殊,你可以说自己精通了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 = newg2o::LinearSolverDense<g2o::BlockSolver<g2o::BlockSolverTraits<3,1> >::PoseMatrixType>();
g2o::BlockSolver< g2o::BlockSolverTraits<3,1> >* solver_ptr = newg2o::BlockSolver< g2o::BlockSolverTraits<3,1> >( linearSolver );
g2o::OptimizationAlgorithmLevenberg* solver = newg2o::OptimizationAlgorithmLevenberg( solver_ptr );
g2o::SparseOptimizer optimizer;
optimizer.setAlgorithm( solver );
模板元(来自ceres的自动求导):
virtualbool Evaluate(double const* const* 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);
}
returninternal::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特征提取部分)
voidFrame::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的深度滤波器):
voidDepthFilter::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的朋友们)
---------------------分割线------------------
题主还提到闭环检测的库,稍微列几个:
DBoW系列,来自TRO12的一篇文章,里头用k-means++训练的字典树。与OpenCV结合紧密,原理亦比较简单。
GitHub -dorian3d/DBoW2: Enhanced hierarchical bag-of-word library for C++
GitHub - rmsalinas/DBow3: Improved version of DBow2
FABMAP系列,用了Chow-Liu树,来自Cummins的一系列论文。作者自己提供过一个开源版本,OpenCV也有人实现了一个,所以一共两种。
FabMap原版
OpenCV:OpenFABMAP
DLoopDetector:在DBoW2基础上开发的回环检测库
https://github.com/dorian3d/DLoopDetector
建议题主从DBoW2或者DBoW3开始入手研究。原理和实现都相对简单一些,效果也比较好。
我自己也在写一本SLAM的书籍,里头带有大量的算法实验。现在还在草稿期,明年出版后题主可以参考一下。鉴于评论区对新书比较感兴趣,那我贴个草稿的目录吧。(由于是草稿所以最后见到的可能会有出入,而且有几节我也还没写完。)所有写着“实践部分”的都附有实例代码。
作者:Kache
https://www.zhihu.com/question/51707998/answer/127351525
研究SLAM,学习的重点应该放在算法上,但是觉得编程也很重要。要验证一些算法,比如闭环检测,视觉里程计等部分,要用什么语言,像比较容易上手和学习的MATLAB能满足吗?
==========================================================
可以应该可以,但是现在有的可用教程并不多。SLAM大多的实现都是基于C++的,尤其是vision SLAM,与闭环检测相关的。在早期的SLAM仿真代码里,其实MATLAB code是不少的,例如Tim Bailey提供了几乎所有早期基于滤波SLAM的仿真实现Homepage of Tim Bailey
还有很多map joining的工作也是matlab的Dr. ShoudongHuang's Personal Page
以及当初Inverse depth 的monoslam 工作Javier Civera
总结,用MATLAB不是不行,但是工作都比较老,新的code不多。但是matlab其实图像处理的工具也很多了,vlfeat,bag-of-words都很成熟了,我觉得如果楼主想尝试的话,其实把论文或者C代码看熟了,做一个matlab的实现也没有问题
看到开源的解决方案中基本都是用C++,除了考虑到效率的问题,还有其他原因吗。是不是自己做算法验证可以不拘泥于编程语言的选择?
==========================================================
1. 效率原因;2. C语言的灵活性和各种库。但是,自己做算法验证可以不拘泥于编程语言的选择。
最近想验证一个闭环检测算法,但是网上找到的代码都是完整的SLAM方案,比如ORB-SLAM, RGBD-SLAM等,请问是否有单独的实现闭环检测的代码可供参考?
==========================================================
有句港句,现在SLAM里面做闭环检测的算法真的很一般很一般,给任何一个CV或者ML出身的人都会说,你们怎么还用这个代码去检测闭环,图像之间的相似性。而如果你想做这个,用MATLAB来做也可以,至于闭环实现的代码,之前已经有人说了,不再赘述。其实我挺鼓励用DL做loop closure detection,现在肯定有人做了。
总问题研究SLAM,对编程的要求有多高?
=========================================================
我觉得还是挺高的,先从后端说起吧
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。理论知识方面基本的Multiviewgeometry其实也就足够了。但是前端的问题在于很多都是经验的东西,参数的选择,循环的次数等等。说白了我个人觉得视觉部分调参的问题更多,理论倒是不容易出问题。
前后段一起的话,什么线程管理就不用说了,该用的库都得上,例如boost啥的。有时候做visualization可能还需要一些别的库。
说完好像要求也就那样,反正我又不是CS出身活得还好好的。
推荐阅读:
重磅!3DCVer-学术论文写作投稿 交流群已成立
扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。
同时也可申请加入我们的细分方向交流群,目前主要有3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。
▲长按加微信群或投稿
▲长按关注公众号
3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近1000+星球成员为创造更好的AI世界共同进步,知识星球入口:
学习3D视觉核心技术,扫描查看介绍,3天内无条件退款
圈里有高质量教程资料、可答疑解惑、助你高效解决问题
来源:oschina
链接:https://my.oschina.net/u/4339343/blog/4336828