研究SLAM,對編程的要求有多高?

點擊上方“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天內無條件退款

 圈裏有高質量教程資料、可答疑解惑、助你高效解決問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章