<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 9563字,需瀏覽 20分鐘

           ·

          2021-09-14 15:27

          點擊上方小白學視覺”,選擇加"星標"或“置頂

          重磅干貨,第一時間送達

          研究SLAM的同學平時除了要看很多頭疼的公式原理外,對編程也是有不少要求的。在學生階段,很多同學都是用MATLAB作為主要編程語言,容易上手又簡單。但是去看SLAM的開源代碼,發(fā)現(xiàn)基本清一色都是C++,而且有不少開源代碼使用C++到了出神入化的地步了。那么問題來了,學習SLAM是否可以不拘泥于編程語言的選擇?到底對編程的要求有多高?

          本文來自知乎上的同名問題,已經(jīng)征得了部分答主的授權(quán),對幾個優(yōu)秀回答進行了整理,如下

          高翔

          關(guān)于MATLAB

          題主說MATLAB,主要原因是大多數(shù)人本科階段接觸的都是MATLAB,所以希望之后研究SLAM也用它。

          MATLAB確實有很多優(yōu)點:語法簡單,開發(fā)速度快,調(diào)試方便,功能豐富。然而,在SLAM領(lǐng)域,MATLAB缺點也很明顯,主要是這兩個:

          • 需要正版軟件(你不能實機上也裝個盜版MATLAB吧);

          • 運行效率不高;

          • 需要一個巨大的安裝包;

          而相對的,C++的優(yōu)勢在于直接使用,有很高的運行效率,不過開發(fā)速度和調(diào)試方面慢于MATLAB。不過光運行效率這一條,就夠許多SLAM方案選擇C++作為開發(fā)語言了,因為運行效率真的很重要。同一個算法,拿MATLAB寫出來實現(xiàn)不能實時,拿C++寫的能實時,你說用哪個?

          當然MATLAB也有一些用武之地。我見過一些SLAM相關(guān)的公開課程,讓學生用MATLAB做仿真,交作業(yè),這沒有問題,比如SLAM toolbox 。同樣的,比較類似于MATLAB的Python(以及octave)亦常被用于此道。它們在開發(fā)上的快捷帶來了很多便利,當你想要驗證一些數(shù)學理論、思想時,這些都是不錯的工具。所謂技多不壓身,題主掌握MATLAB和Python當然是很棒的。

          但是一牽涉到實用,你會發(fā)現(xiàn)幾乎所有的方案都在用C++。因為運行效率實在是太重要了。

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

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

          接下來說說C++大概要學到什么程度。用程序員的話說,C++語言比較特殊,你可以說自己精通了Java,但千萬不要說自己精通了C++。C++非常之博大精深,有數(shù)不清的特性,而且隨著時間還會不斷變化更新。不過,大多數(shù)人都用不著學會所有的C++特性,因為許多東西一輩子都用不到。

          作為SLAM研究人員,我們面對的主要是算法層面的開發(fā),所以更關(guān)心如何有效地實現(xiàn)各種相關(guān)的算法。而相對的,那些復雜的軟件架構(gòu),設(shè)計模式,我個人認為在SLAM中倒是占次要地位的。畢竟您用SLAM的目的是計算一個位置以及建個地圖,并不是要去寫一套能夠自動更新的、多人網(wǎng)上對戰(zhàn)功能的機器人大戰(zhàn)平臺。您的主要精力可能會花在矩陣運算、分塊、非線性優(yōu)化的實現(xiàn)、圖像處理上面;您可能對并發(fā)、指令集加速、GPU加速等話題感興趣,也可以花點時間學習;你還可能想用模板來拓展你的算法,也不妨一試。相應的,很多功能性的東西,比如說UI、網(wǎng)絡(luò)通信等等,當你用到的時候不妨接觸一下,但專注于SLAM上時就不必專門去學習了。

          話雖如此,SLAM所需的C++水平,大抵要高于你在書本上看到的那些個示例代碼。因為那些代碼是作者用來向初學者介紹語法的,所以會盡量簡單。而實際見到的代碼往往結(jié)合了各種奇特的技巧,乍看起來會顯得高深莫測。比方說你在教科書里看的大概是這樣:

          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;
          }

          我不知道你們看到這些代碼是什么心情,總之我當時內(nèi)心的感受是:臥槽這怎么和教科書里的完全不一樣?。《已芯苛税胩彀l(fā)現(xiàn)人家居然是對的?。?/span>

          [我不是很擅長貼表情圖總之你們腦補一下就好]

          總而言之,對C++的水平要求應該是在教科書之上的。而且這個水平的提高,多數(shù)時候建立在你不斷地看別人代碼、碼自己代碼的過程之上。它是反復練習出來的,并不是僅僅通過看書就能領(lǐng)會的。特別是對于視覺SLAM問題,很多時候你沒法照著論文把一套方案實現(xiàn)出來,這很大程度上取決于你的理論和代碼功底。

          所以,請盡早開始學習C++,盡早開始使用C++,才是研究SLAM的正確之道。不要長期彷徨在自己的舒適區(qū)里猶豫不決,這樣是沒有進步的。(同樣的道理亦適用于想研究SLAM但不愿意學習Linux的朋友們)

          Kache

          我覺得對編程要求還是挺高的,先從后端說起吧
          g2o, gtsam,ceres知道是肯定需要知道的,三者其實學習曲線都挺難的,你覺得你會用了是一回事,然后用好是一回事,自己寫vertex, edge, factor, cost function又是另外一回事,如果你會寫g2o里面的solver應該又是一個級別了吧。但是這三個在網(wǎng)上的資源而論g2o > ceres > gtsam。再者,你會調(diào)用api就代表你懂優(yōu)化了嗎,自己動手matlab寫一下gauss-newton應該也可以試一試吧。當然,遠古一點了levmar也很不錯哦。直到這里,你確定你明白各種算法底層suitesparse里面的效率問題嗎,如果挖掘到了這一層,還有各種線性代數(shù)庫的比較哦,肯定是又快有慢。所以說,想要學會一到兩個優(yōu)化器不難,學會自定義有一點難,考慮到后端的效率自己寫solver更難,深入到線性代數(shù)庫的最底層,考慮問題結(jié)構(gòu),提升效率就更難了

          前端,其實僅僅考慮點特征,也就那么多東西,V-SLAM用OPENCV也就夠用了,而且opencv我覺得到API調(diào)用那一層也就足夠了。如果考慮上RGBD,再加上一個PCL。理論知識方面基本的Multiview geometry其實也就足夠了。但是前端的問題在于很多都是經(jīng)驗的東西,參數(shù)的選擇,循環(huán)的次數(shù)等等。說白了我個人覺得視覺部分調(diào)參的問題更多,理論倒是不容易出問題。

          前后段一起的話,什么線程管理就不用說了,該用的庫都得上,例如boost啥的。有時候做visualization可能還需要一些別的庫。

          說完好像要求也就那樣,反正我又不是CS出身活得還好好的

          邵天蘭

          要搞SLAM,編程能力非常非常重要。編程能力就像運動員的力量和體能,是一切技巧和戰(zhàn)術(shù)的基礎(chǔ)。雖然研究的是算法,但良好的編程能力能夠使你節(jié)省大量的時間,并且達到更好的效果。

          根據(jù)我的經(jīng)驗,算法搞得特別好的人很少有編程不行的,因為編程好可以使你能夠迅速驗證想法。見過不少學生因為編程基礎(chǔ)不好,在實現(xiàn)和debug上浪費大把大把的時間。這樣的人當然很難把算法搞好。

          這里編程能力有很多方面,以下簡單說幾個。贊多了再補( ̄▽ ̄)/

          1. 閱讀代碼的能力
          未說寫,先說讀。搞科研和搞工程都大忌閉門造車,除了paper外,開源代碼是最有效的學習途徑。一般而言,paper中只是著重描述比較創(chuàng)新的部分,80%以上的實現(xiàn)細節(jié)(甚至很多很關(guān)鍵的東西)需要從代碼中了解。編程不好的人,往往也不太會讀代碼。

          2. 架構(gòu)軟件,管理復雜項目的能力
          一個SLAM方案通常由很多模塊組成。我見過不少實驗室的內(nèi)部代碼,一鍋粥,學生們各種胡亂修補。這樣必然導致效率低下。如果能做到模塊化、低耦合,可以使開發(fā)事半功倍。

          3. 高效實現(xiàn)的能力
          過去八年間,我最少的一年也碼了兩萬多行。。。根據(jù)我的體會,同樣的算法,好的實現(xiàn)可以比不好的實現(xiàn)快2-10倍。復雜度越高越如是,例如3D  SLAM。要擁有高效實現(xiàn)的能力,必須熟悉常用的數(shù)據(jù)結(jié)構(gòu),對復雜度分析形成很好的直覺。

          4. 管理多線程、異步程序的能力
          SLAM往往涉及到多線程和異步程序,例如用于后端優(yōu)化等。玩兒不轉(zhuǎn)這個就會出現(xiàn)程序不穩(wěn)定,或效率低。

          Matlab不能滿足需要。Matlab對數(shù)據(jù)結(jié)構(gòu)的支持太差,而且速度慢。即使不考慮產(chǎn)品,只是做算法,也很不適合。自己做算法驗證基本上就是C++或python,如果你因為不熟悉這些而選其他語言,會因為參考少、輪子少的原因效率很低。強烈建議題主學習C++。

          好消息,小白學視覺團隊的知識星球開通啦,為了感謝大家的支持與厚愛,團隊決定將價值149元的知識星球現(xiàn)時免費加入。各位小伙伴們要抓住機會哦!


          下載1:OpenCV-Contrib擴展模塊中文版教程
          在「小白學視覺」公眾號后臺回復:擴展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴展模塊教程中文版,涵蓋擴展模塊安裝、SFM算法、立體視覺、目標跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實戰(zhàn)項目52講
          小白學視覺公眾號后臺回復:Python視覺實戰(zhàn)項目,即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實戰(zhàn)項目,助力快速學校計算機視覺。

          下載3:OpenCV實戰(zhàn)項目20講
          小白學視覺公眾號后臺回復:OpenCV實戰(zhàn)項目20講,即可下載含有20個基于OpenCV實現(xiàn)20個實戰(zhàn)項目,實現(xiàn)OpenCV學習進階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 82
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产毛片18水真多18精品 | 欧美男女日逼视频 | 久久91欧美特黄A片 | 久久不卡视频精典视频 | 亚洲国产欧美日韩在线 |