現在是晚上22點46分(注2020年12月11日),大小美女都睡覺了,我突然想寫一篇這五年無人駕駛工作的總結。沒有打草稿,想到啥說啥。如有不對的地方,請大家指正。我從事無人駕駛是從2016年初開始的,機緣巧合之下被伯樂選中,原因是我的專業是控制理論與控制工程,可是我本人對控制一點興趣沒有,就喜歡編程。當時自學了java,面試很容易就過了,也是因為單位當時的現狀是矮子里面找高個,挑無可挑了,算是趕鴨子上架吧。現在非常感謝當時的那位領導,要不是他,我學不到這么多受用終身的知識。其實從2014年開始,國外的無人駕駛已經進入了高速發展,當時國內都在炒房、炒股、炒比特幣,所以起步就已經落后了。當時就沒聽過深度學習、機器學習,只在學校里學習過神經網絡、免疫算法等,感覺就是參數優化和大范圍隨機搜索,沒學到精髓。我非常榮幸的見證了我國某代軍車的研發和制造過程,從初樣車到正樣車,再到定型車,最后量產。團隊的無人駕駛工作也在這款軍車上開展,目的是為了在未來某天,能夠接到軍方的項目,提升車輛的二次開發價值。2016年國內的無人駕駛開始預熱,各大主機廠、科技公司都開始入場,高校在理論方面更是走到了前面,畢竟高校的知識儲備太豐富。開始的目標很簡單,實現軌跡跟蹤就行,盡量提高車輛速度和控制穩定性。在當時只有三個人的情況下,從一臉懵逼到實現預期目標。寫過前端控制界面,也干過軌跡規劃,都是用c#寫的,當時根本不懂去用linux,更別提ros,c++了。當時是真的莽,真敢坐車上測試,現在有些后怕。控制用的PID,軌跡跟蹤用的預瞄,簡單而且效果好,算是入行了吧。2017年,在前一年的基礎上實現了車道保持,車道預警,車道線識別,變道等功能。傳感器使用了一個mobileye和慣性導航,最高車速55,坐車上是真的害怕,手就放在急停按鈕上,一旦有險情直接急剎。通過實踐,發現了用c#的不足,首先編寫前端界面很麻煩,不光要實現控制,還需要將車輛軌跡和mobileye檢測的障礙物呈現出來。當時也不懂什么多線程、多進程,就是在主線程里整,這會影響到控制的實時性,好在當時沒有出問題。其次,擴展性差,當加入其他功能單元或者傳感器后,需要改動程序,很麻煩。最后是調試不方便。這也是我學藝不精,其實c#功能很強大,只是用錯了地方。2018年,我們終于換了系統,在ubuntu下使用ros,編程語言也切換成了c++。為了學c++,翻了書,也抄了一個github上的開源代碼,從頭抄到尾,這樣就熟悉了c++的語法和編寫方式。抄代碼是個笨辦法,我是比較笨的那種人,如果只看書、看教程,我看了就忘,跟沒看一樣。原來上課的時候老師就說,編程編程,你得去編啊,動手才是王道。由于人員的擴充,我更換了研究方向,終于不用在編寫界面了,跳進了坑了我3年的激光雷達領域,這個坑是真的大,一直到現在我還在坑底,努力的向上爬。當時接激光雷達是在年底了,目標是用激光雷達識別目標,主要是車輛、行人以及在一定范圍內的所有靜態障礙物,并且跟蹤障礙物運動狀態。先使用4線激光雷達,雷達本身能直接輸出檢測的障礙物。后來4線的效果只在平面內,不能實現3d成像,所以改用velodyne16線為主,4線補盲的方式。第一次看到密密麻麻的點云數據,真的是一臉懵逼,這到底是啥啊,我就靠這些點能識別出障礙物嗎?搞笑呢吧。為了實現目標,去學習了pcl庫。通過閱讀pcl庫的某些源代碼,了解了點云的處理方式和一些基礎算法。最后使用了歐式聚類,實現了在城市道路上的目標檢測。這種目標檢測有很多的局限性。1. 得先識別地面,然后去掉地面。2. 需要去掉空中的點,比如樹冠等,因為我只關心車輛前方道路上和道路兩側的低空障礙物。3. 歐式聚類設置一個距離閾值,只有點與點間的距離小于閾值時才算做同一個障礙物。如果兩個障礙物距離近,將會有很大概率識別成同一個物體,也就會將路邊停的一排家用車識別成一個大平板。識別距離是40米,縱向誤差小于0.5米,橫向誤差小于0.3米。算是達到了預期效果。實驗過程中發現了一些問題,首先,16線激光雷達更適合補盲,線太少,如果作為主要傳感器,探測距離太近,在40米外的障礙物可能只是一條水平直線。其次,在障礙物密集的場景,運算速度下降。最后,由于沒有識別道路邊界,無法識別障礙物是否在前方道路內。時間來到了2019年,目標是:1. 提高激光雷達目標識別精度、距離、運算速度;2. 識別道路邊界,擬合邊界曲線。首先是目標識別,之前看了一篇關于凸平面分割障礙物的文章,覺得特別有道理,重要的是可以分割的很精確。沿著這個方向查了相關資料,發現了一篇論文《Object Partitioning using Local Convexity》,閱讀淪為,并搞懂了算法原理。文章中給出了在pcl庫中的實現,名字叫LCCP,可惜使用在圖像上。圖像和點云有很強的相似性,都是由點組成,只不過一個是像素,一個是xyz。像素點在經過相機內參和外參變換后,就會映射到三維空間。算法上也有很多相通點,我所知道的特征提取還有金字塔算法都可以通用,只需要將點云在三維空間中結構化,比方說八叉樹等。(說實話,我知道的圖像處理知識很有限,如果錯了,請給我留言說一聲,感謝。)經過修改后,將LCCP用在了點云上。激光雷達LCCP算法效果圖這就是處理的效果圖,能夠描述車輛的外形輪廓。但就是計算速度慢,得170ms+,無法實時處理點云數據,不適合無人駕駛,但是如果用在離線處理,比如slam上去除動態目標物,興許效果更好,我沒有嘗試。運算速度慢的原因是體素過濾后計算了每個點的法向量,使用周邊一定距離內的所有點進行主成分析,體素過小和周邊點太多導致計算緩慢,畢竟需要計算每個點的法向量,然后再區域生長聚合目標物。我嘗試了擴大體素和使用最近的若干點,雖然提高了計算速度,但是輪廓精度降低很多。在這種兩難的場景下,我更傾向于保證精度,所以將代碼保留,如果以后做slam可以使用。LCCP的編寫和調試花廢了太長時間,效果又沒有達到預期。所以不得不立刻改變方向,加快進度,如果年底目標達不到,扣錢是肯定的。在金錢的誘惑下,我給屁股上扎了兩針雞血~~~。更改的方向鎖定在速度快,越快越好,精度不能太低,識別距離50米以上。最后發現了這篇神文--Fast Multi-Pass 3D Point Segmentation Based on a Structured Mesh Graph for Ground Vehicles。算法實現后是真的快,單32線雷達只需要17ms,一個32線加兩個16線融合后只需要22ms,我驚了。看到結果圖的瞬間,我感覺已經達到了人生的巔峰,并且已經保證不用扣錢了,獲取還能獎勵點(做夢)。算法的核心思想就是利用激光雷達的數據分層結構,論文中有一步擬合多項式,我去掉了,原因是會拖慢運算速度,而且效果也沒有多大提升。年底時,用這套目標識別算法,再加上去年的目標跟蹤,成功的在環境較為復雜的路面實現了無人駕駛。環境是一半越野路,一半公路,甚至了S形彎道等,實驗結果達到了既定目標。不足之處:1. 3個雷達數據融合存在問題,我選擇目標級別融合,也就是先識別目標物,然后目標物融合跟蹤。只有障礙物被跟蹤若干周期后,等它穩定并且長期存在后,再輸出給控制層,這就導致滯后。滯后的這幾個周期會對控制有很大影響,車速慢就罷了,一旦車速快就會發生碰撞或剮蹭。2. 識別距離短,剛好達到50米的最低要求,分析原因是32線雷達斜向下安裝,前向線不足導致,但是32線如果水平裝,就會產生很大盲區,雷達安裝離地大概有2.5米到3米。道路邊界識別沒啥好說的,就是先識別馬路牙子或者隔離帶或者護欄,然后線性擬合。我們有同事加入了kalman濾波,道路邊界曲線穩定性有了極大提高。2020年,人員再次擴充,我交出了目標識別的工作,轉向SLAM。這個領域是我接觸激光雷達開始就強烈希望去做的,但是得根據團隊的規劃走,所以一直拖到了現在。當知道我能做SLAM后,你們想象不到我的快樂!!!激光slam沒有攝像頭slam那樣熱門,但是也有很多非常出名的算法。我首先求助的是google的開源項目cartogrpher。這個算法是真的牛逼,就靠概率累加和有限范圍搜索,實現了實時slam。閱讀源碼后不得不感嘆google的神仙是真的牛逼。cartographer的2D和3D的實現差別是點云的空間結構上,2D是平面柵格,3D是八叉樹結構,其他算法都一樣。只是cartographer中使用按一定區間旋轉和平移點云,進行輪尋式的匹配,以此作為回環檢測,實際使用時,會出現匹配錯誤的情況,再加入IMU數據后會好轉,但是如果縮小每步的旋轉和平移,會增加計算時間。后來,團隊覺得cartographer是掃地機器人的核心算法,用在無人車上不靠譜,無人車要3D,再解釋無果的情況下,也是為了保住我能做SLAM,更換算法,轉到了Lego-SLAM。Lego-SLAM是使用了提取點云特征,匹配相鄰兩幀間特征點計算相對姿態變換,回環檢測使用和當前幀最近的若干幀進行匹配,檢測是否存在循環,在使用圖優化進行全局優化。可以使用IMU數據,也可以不使用,當然使用了精度更高。還有一個種叫SC-lego-loam,在回環檢測中使用了scanContext,這種算法太巧妙了,適合在雷達高度固定的場景。團隊又說了,loam很好,但是IMU卻沒有起到關鍵作用,應該使用IMU數據和GPS數據對slam進行矯正,我覺得也對,畢竟傳感器越多越精確,誠摯的接受團隊建議,再次修改方向。最后使用了hdl_graph_slam,傳感器包含雷達、IMU、GPS,匹配算法使用了變種NDT集合圖優化,回環檢測依然是在距離最近的若干關鍵幀中尋找。該變種NDT修改了臨近點的數量,從26變到了7,并且在求每個點的梯度和hessian時使用了openmp的多線程方法,極大的加速了運算速度。最近,在刷知乎的時候看了一篇slam發展趨勢的文章,里面提到了語義建圖,而且國外的學術會議有關語義建圖的論文越來越多。我個人認為無人駕駛已經從算法驅動向著數據驅動發展了,引入深度學習才是王道。所以最近在研究Suma,opengl看不懂,glow看不懂,要搞懂Suma和Suma++還得研究下。以上提出得幾種SLAM算法,我寫了詳細的源碼解析,但是沒有整理,待我整理完,在逐一發出。最后,說一些我的感悟:1. 無人駕駛。無人駕駛現在冷卻了下來,從科技公司到政府都希望盡快落地。今年百度的無人駕駛出租車已經在海淀和長沙等地試運行了。這其中最明顯的認知變化就是無人駕駛目前只能在限定場景下實現,特斯拉的幾次事故就已經說明了這一點。在類似沙盒的場景下,要處理的環境信息太多,隨時都可能發生意想不到的情況,深度學習對這種可能出現的意外缺乏數據支撐,沒有辦法作出正確決定。連特斯拉都不敢再吹牛逼,但當我看到國內主機廠吹自己實現了L4、L5級別的無人駕駛,我真的很無語,國內的無人駕駛一直很浮躁,沉下心,少吹牛逼,默默追趕才是出路,花拳繡腿終歸比不過冬練三九夏練三伏。2. 關于代碼造輪子。網上很多人說編程的大忌就是造輪子。但是算法你不造輪子不行啊,只會用庫,不懂原理,你連修改都沒法改,沒有辦法根據目標的變化修改代碼,很被動。所以,算法造輪子不能偷懶,該造還得造,還得好好造,多編多練才能取得進步。3. 我覺得V2X是未來無人駕駛的強大甚至是核心助力,物聯網,嘖嘖,想著就牛逼。4. 跟著國外走吧,國內的主機廠都在搞笑,他們很少真正關心技術,關心的只是項目完成,年底拿錢。請保持一顆追趕超越的心。注:點擊閱讀原文,關注作者知乎