日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

[笔记]三维激光SLAM学习——LiDAR里程计原理推导代码实现

發布時間:2023/12/3 综合教程 60 生活家
生活随笔 收集整理的這篇文章主要介紹了 [笔记]三维激光SLAM学习——LiDAR里程计原理推导代码实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[筆記]三維激光SLAM學習——LiDAR里程計原理推導&代碼實現

  • [筆記]三維激光SLAM學習——LiDAR里程計原理推導&代碼實現
  • 前言
  • 一、LiDAR里程計原理
    • 1、坐標系定義
    • 2、特征點提取
    • 3、特征點匹配
      • 3.1、計算對應特征的距離
    • 4 、用非線性優化方法進行運動估計
      • 4.1、幀間運動的雅克比J的推導
  • 二、LOAM的LiDAR里程計代碼分析
    • 1、ROS訂閱和發布
    • 2、初始化
    • 3、點云處理——點云配準與運動估計
      • 3.1、邊緣特征上的點配準
      • 3.2、平面特征上的點配準
      • 3.3、構建Jaccobian并進行運動估計求解
    • 4、坐標轉換

[筆記]三維激光SLAM學習——LiDAR里程計原理推導&代碼實現

前言

最近看回來之前發的博客,發現了埋了很多坑,其中也有很多錯誤的地方,所以現在重新寫一遍,一個個坑補回來。

一、LiDAR里程計原理

簡述:目前用得比較多的還是LOAM中提出的方法,以一個粗糙度ccc值來區分邊緣和平面,然后邊緣點、平面點分別與邊緣線、平面匹配,從而得到一個兩幀之間的LiDAR位姿。

簡單地說,就是提取銳利邊緣特征點和平面特征點,并分別將特征點邊緣線段平面曲面片進行匹配。

參考文獻:Zhang J , Singh S . Low-drift and Real-time Lidar Odometry and Mapping[J]. Autonomous Robots, 2017, 41(2):401-416.

1、坐標系定義

  • 激光雷達坐標系L{L}L是3D坐標系,其原點位于激光雷達的幾何中心。 xxx軸指向左側,yyy軸指向上方,zzz軸指向前方。
  • 世界坐標系W{W}W是在初始位置與L{L}L一致的3D坐標系。

2、特征點提取

LOAM論文中選擇在銳利邊緣平面/曲面的特征點。設iii為PkP_kPk?中的一個點,i∈Pki∈P_ki∈Pk?,設SSS為LiDAR在同一掃描中返回的iii的連續點集。定義一個“粗糙度”ccc來評估局部曲面的平滑度,用于邊緣特征點平面特征點普通點的分類。
(這個粗糙度可以粗暴的理解為點iii到鄰點的距離之和)
c=1∣S∣?∥X(k,i)L∥∥∑j∈S,j≠i(X(k,i)L?X(k,j)L)∥c=\frac1{\left|\boldsymbol S\right|\cdot\left\|\boldsymbol X_{\left(k,i\right)}^L\right\|}\left\|\sum_{j\in\boldsymbol S,j\neq i}(\boldsymbol X_{(k,i)}^{\boldsymbol L}-\boldsymbol X_{(k,j)}^{\boldsymbol L})\right\|c=∣S∣?∥∥∥?X(k,i)L?∥∥∥?1?∥∥∥∥∥∥?j∈S,j?=i∑?(X(k,i)L??X(k,j)L?)∥∥∥∥∥∥?

  • 掃描中的點根據ccc值進行排序,然后用最大ccc值(即邊緣點)和最小ccc值(即平面點)選擇特征點。
  • 一次掃描分為四個均等的區域。每個區域中最多可提供2個邊緣點4個平面點。

兩點約束:

  • 不能位于與激光束大致平行的曲面片上
  • 不能位于遮擋區域的邊界上

    因為這些點通常被認為是不可靠的。

3、特征點匹配


設tkt_ktk?為掃描kkk的開始時間,在開始時,PkP_{k}Pk?是一個空集,在掃描過程中隨著接收到更多點而增加。在每次掃描結束時,在掃描過程中感知到的點云PkP_kPk?重新投影到時間戳tk+1t_{k+1}tk+1?,如上圖所示。然后將重新投影的點云表示為P ̄k{\overline P}_{k}Pk?。在下一個掃描k+1k+1k+1期間,P ̄k{\overline P}_{k}Pk?與新接收的點云Pk+1P_{k + 1}Pk+1?一起估計激光雷達的運動。
假設P ̄k{\overline P}_{k}Pk?和Pk+1P_{k+1}Pk+1?現在都可用,并開始尋找兩個激光雷達點云之間的對應關系。從Pk+1P_{k+1}Pk+1?中找到邊緣特征點平面特征點,設Ek+1E_{k+1}Ek+1?和Hk+1H_{k+1}Hk+1?分別為邊緣特征點平面特征點的集合。我們將從P ̄k{\overline P}_{k}Pk?中找邊緣線作為Ek+1E_{k+1}Ek+1?中的邊緣特征點對應,以及從P ̄k{\overline P}_{k}Pk?中找平面塊作為Hk+1H_{k+1}Hk+1?中的平面特征點對應。
在掃描k+1{k+1}k+1開始時,Pk+1P_{k+1}Pk+1?是一個空集,在掃描過程中隨著接收到更多點而增加。激光雷達里程計遞歸地估計掃描過程中的6自由度運動,并隨著Pk+1P_{k+1}Pk+1?的增加逐漸包含更多的點。在每次迭代中,使用當前估計的變換,將Ek+1E_{k+1}Ek+1?和Hk+1H_{k+1}Hk+1?重新投影到掃描的開始。將重新投影的點集設為E~k+1{\widetilde E}_{k+1}Ek+1?和H~k+1{\widetilde H}_{k+1}Hk+1?。對于E~k+1{\widetilde E}_{k+1}Ek+1?和H~k+1{\widetilde H}_{k+1}Hk+1?中的每個點,我們將在P ̄k{\overline P}_{k}Pk?中找到最近的相鄰點。這里,P ̄k{\overline P}_{k}Pk?存儲在3D KDtree中,用于快速索引。

邊緣特征點與邊緣線對應
上圖(a)表示尋找邊緣線作為邊緣特征點的對應關系的過程。設iii為E~k+1,i∈E~k+1{\widetilde E}_{k+1},i∈{\widetilde E}_{k+1}Ek+1?,i∈Ek+1?中的點。邊緣線由兩點表示。設jjj為iii在P ̄k{\overline P}_{k}Pk?中的最近鄰,j∈P ̄kj∈{\overline P}_{k}j∈Pk?,設lll為iii在連續兩次掃描中iii的最近鄰。(j,l)(j,l)(j,l)形成了iii的對應關系。然后,為了驗證jjj和lll都是邊緣點,我們根據ccc值檢查局部表面的光滑度。在這里,我們特別要求jjj和lll來自不同的掃描,因為單個掃描不能包含來自同一邊緣線的多個特征點。邊緣線在掃描平面上只有一個例外。但是,如果是這樣,則邊緣線將退化并在掃描平面上顯示為直線,并且邊緣線的特征點不應首先提取。
平面特征點與平面曲面塊對應
上圖(b)表示尋找平面曲面塊作為平面特征點的對應關系的過程。設iii為H~k+1{\widetilde H}_{k+1}Hk+1?中的點,i∈H~k+1i∈{\widetilde H}_{k+1}i∈Hk+1?。平面斑塊由三個點表示。與上一部分相似,我們在P ̄k{\overline P}_{k}Pk?找到iii的最近鄰,表示為jjj。然后,我們找到另外兩個點lll和mmm,它們是iii的最近鄰,一個點與jjj在同一掃描中,另一個在兩次連續掃描中直到jjj的掃描中。這保證了這三個點是非共線的。為了驗證jjj,lll和mmm均為平面點,我們基于ccc值再次檢查局部表面的光滑度。

3.1、計算對應特征的距離

利用找到的特征點的對應關系,現在我們導出表達式以計算從特征點到其對應關系的距離。下面將通過最小化特征點的總距離來估計激光雷達運動。
邊緣特征點距離計算:
對于點i∈E~k+1i∈{\widetilde E}_{k+1}i∈Ek+1?,如果(j,l)(j,l)(j,l)是相應的邊緣線j,l∈P ̄kj,l∈{\overline P}_{k}j,l∈Pk?,則點到線的距離可以計算為

其中,X~(k+1,i)L{\widetilde X}_{(k+1,i)}^{\boldsymbol L}X(k+1,i)L?,X ̄(k,j)L{\overline X}_{(k,j)}^{\boldsymbol L}X(k,j)L?和X ̄(k,l)L{\overline X}_{(k,l)}^{\boldsymbol L}X(k,l)L?分別是L{L}L中點iii,jjj和lll的坐標。
直觀理解:公式的分子是兩個向量的叉乘,而叉乘后求模就變成了求兩個向量構成的三角形的面積。公式的分母是向量的模相當于三角形底邊的長。三角形面積除以一條邊就可以求出該邊到對應頂點的距離,也就是邊角點到邊角線的距離。直觀上的理解如下圖所示:

平面特征點距離計算:
對于點i∈H~k+1i∈{\widetilde H}_{k+1}i∈Hk+1?,如果(j,l,m)(j,l,m)(j,l,m)是對應的平面曲面塊j,l,m∈P ̄kj,l,m∈{\overline P}_{k}j,l,m∈Pk?,則點到平面的距離為

其中,X ̄(k,m)L{\overline X}_{(k,m)}^{\boldsymbol L}X(k,m)L?是L{L}L中點mmm的坐標。
直觀理解:公式的分子包括兩部分,上邊是獲得一個向量,下邊也是獲得一個向量,但兩個向量叉乘再取模就表示的求下邊得到三角形面積,上面表示立方體的高,兩者相乘就表示立方體體積。而分母表示立方體底面三角形的面積,得到的高就是平面點到平面的距離。直觀上的理解如下圖所示:

4 、用非線性優化方法進行運動估計

回想一下,上式計算E~k+1{\widetilde E}_{k+1}Ek+1?和H~k+1{\widetilde H}_{k+1}Hk+1?中的點之間的距離及其對應關系。結合邊緣特征點距離計算式和上邊的式子,我們可以得出Ek+1E_{k + 1}Ek+1?中的邊緣點與相應邊緣線之間的幾何關系,

類似地,結合平面特征點距離計算式和上邊的式子,我們可以在Hk+1H_{k + 1}Hk+1?中的一個平面特征點和相應的平面塊之間建立另一個幾何關系,

最后,利用非線性優化的方法求解激光雷達的運動。對于Ek+1E_{k + 1}Ek+1?和Hk+1H_{k + 1}Hk+1?中的每個特征點fEf_EfE?與fHf_HfH?相加,我們得到一個非線性函數。

其中fff的每一行對應一個特征點,ddd包含相應的距離。我們計算相對于Tk+1L{T}_{k+1}^{\boldsymbol L}Tk+1L?的fff的雅可比矩陣,記為JJJ,其中J=?f/?Tk+1LJ =?f/?{T}_{k+1}^{\boldsymbol L}J=?f/?Tk+1L?。然后將ddd最小化為零,通過使用高斯-牛頓法(GN法)JTJX=?JTfJ^TJX=-J^TfJTJX=?JTf迭代來求解上式。這里涉及到一個幀間運動的雅克比矩陣JJJ,下面我們來推導一下。

4.1、幀間運動的雅克比J的推導


對于一幀點云數據,有第一個點psp_sps?和最后一個點pep_epe?,以及任意時刻的點ptp_tpt?。
首先,將任意時刻ttt的點重新投影到同一時刻tst_sts?得到點p~st{\widetilde p}_{st}p?st?,則得到以下式子
pt=Rs:tp~st+ts:tp_t=R_{s:t}{\widetilde p}_{st}+t_{s:t}pt?=Rs:t?p?st?+ts:t?p~st=Rs:t?1(pt?ts:t){\widetilde p}_{st}=R_{s:t}^{-1}(p_t-t_{s:t})p?st?=Rs:t?1?(pt??ts:t?)
根據上邊的坐標系定義,使用左乘旋轉矩陣,旋轉坐標軸順序Z-X-Y得到旋轉矩陣RZXYR_{ZXY}RZXY?
Rs:t=RZXY=RryRrxRrzR_{s:t}=R_{ZXY}=R_{ry}R_{rx}R_{rz}Rs:t?=RZXY?=Rry?Rrx?Rrz?=[cosry0sinry010?sinry0cosry][1000cosrx?sinrx0sinrxcosrx][cosrz?sinrz0sinrzcosrz0001]= \begin{bmatrix} cosry& 0& sinry\\ 0& 1& 0\\ -sinry& 0& cosry \end{bmatrix} \begin{bmatrix} 1& 0& 0\\ 0& cosrx& -sinrx\\ 0& sinrx& cosrx \end{bmatrix} \begin{bmatrix} cosrz& -sinrz& 0\\ sinrz& cosrz& 0\\ 0& 0& 1 \end{bmatrix}=???cosry0?sinry?010?sinry0cosry???????100?0cosrxsinrx?0?sinrxcosrx???????cosrzsinrz0??sinrzcosrz0?001????=[cry?crz+sry?srx?srzcrz?sry?srx?cry?srzcrx?srycrx?srzcrx?crz?srxcry?srx?srz?crz?srycry?crz?srx+sry?srzcry?crx]= \begin{bmatrix} cry*crz+sry*srx*srz& crz*sry*srx-cry*srz& crx*sry\\ crx*srz& crx*crz& -srx\\ cry*srx*srz-crz*sry& cry*crz*srx+sry*srz& cry*crx \end{bmatrix} =???cry?crz+sry?srx?srzcrx?srzcry?srx?srz?crz?sry?crz?sry?srx?cry?srzcrx?crzcry?crz?srx+sry?srz?crx?sry?srxcry?crx????
下式用ccc代表coscoscos函數,sss代表sinsinsin函數:
Rs:t?1=[cry?crz?srx?sry?srzcry?srz+srx?sry?crz?sry?crx?crx?srzcrx?crzsrxsry?crz+srx?cry?srzsry?srz?srx?cry?crzcry?crx]R_{s:t}^{-1} =\begin{bmatrix} cry*crz-srx*sry*srz& cry*srz+srx*sry*crz& -sry*crx\\ -crx*srz& crx*crz& srx\\ sry*crz+srx*cry*srz& sry*srz-srx*cry*crz& cry*crx \end{bmatrix}Rs:t?1?=???cry?crz?srx?sry?srz?crx?srzsry?crz+srx?cry?srz?cry?srz+srx?sry?crzcrx?crzsry?srz?srx?cry?crz??sry?crxsrxcry?crx????
對于Rs:t?1R_{s:t}^{-1}Rs:t?1?有Rs:t?1=RZXY?1=RYXZTR_{s:t}^{-1}=R_{ZXY}^{-1}=R_{YXZ}^TRs:t?1?=RZXY?1?=RYXZT?
雅克比計算:
f(p~st)=f(Rs:t?1(pt?ts:t))=f(Rs:t?1,ts:t)=df({\widetilde p}_{st})=f(R_{s:t}^{-1}(p_t-t_{s:t}))=f(R_{s:t}^{-1},t_{s:t})=df(p?st?)=f(Rs:t?1?(pt??ts:t?))=f(Rs:t?1?,ts:t?)=d
定義:Rs:t?1R_{s:t}^{-1}Rs:t?1?對應的旋轉角分別為rx,ry,rzrx,ry,rzrx,ry,rz即Rs:t?1=RZXY=RryRrxRrzR_{s:t}^{-1}=R_{ZXY}=R_{ry}R_{rx}R_{rz}Rs:t?1?=RZXY?=Rry?Rrx?Rrz?ts:tt_{s:t}ts:t?分量分別為tx,ty,tzt_x,t_y,t_ztx?,ty?,tz?即ts:t=[tx,ty,tz]Tt_{s:t}=[t_x,t_y,t_z]^Tts:t?=[tx?,ty?,tz?]T
進一步得到:?f?Tk+1L=?f?(rx,ry,rz,tx,ty,tz)=[?f?rx,?f?ry,?f?rz,?f?tx,?f?ty,?f?tz]\frac{\partial f}{\partial T^L_{k+1} }=\frac{\partial f}{\partial (rx,ry,rz,tx,ty,tz)}=[\frac{\partial f}{\partial rx},\frac{\partial f}{\partial ry},\frac{\partial f}{\partial rz},\frac{\partial f}{\partial tx},\frac{\partial f}{\partial ty},\frac{\partial f}{\partial tz}] ?Tk+1L??f?=?(rx,ry,rz,tx,ty,tz)?f?=[?rx?f?,?ry?f?,?rz?f?,?tx?f?,?ty?f?,?tz?f?]

式1?f?rx=?f?p~st?p~st?rx\frac{\partial f}{\partial rx }=\frac{\partial f}{\partial {\widetilde p}_{st}} \frac{\partial {\widetilde p}_{st}}{\partial rx}?rx?f?=?p?st??f??rx?p?st??=[la,lb,lc]?Rs:t?1?rx(pt?ts:t)=[la,lb,lc] \frac{\partial R_{s:t}^{-1}}{\partial rx }(p_t-t_{s:t})=[la,lb,lc]?rx?Rs:t?1??(pt??ts:t?)=[la,lb,lc]?Rs:t?1?rx[pxpypz]?[la,lb,lc]?Rs:t?1?rx[txtytz]=[la,lb,lc]\frac{\partial R_{s:t}^{-1}}{\partial rx} \begin{bmatrix} px\\py\\pz\\ \end{bmatrix}-[la,lb,lc]\frac{\partial R_{s:t}^{-1}}{\partial rx}\begin{bmatrix} tx\\ty\\tz\\ \end{bmatrix}=[la,lb,lc]?rx?Rs:t?1?????pxpypz?????[la,lb,lc]?rx?Rs:t?1?????txtytz????

式2?f?tx=?f?p~st?p~st?tx\frac{\partial f}{\partial tx }=\frac{\partial f}{\partial {\widetilde p}_{st}} \frac{\partial {\widetilde p}_{st}}{\partial tx}?tx?f?=?p?st??f??tx?p?st??=[la,lb,lc]Rs:t?1[?100]=[la,lb,lc]R_{s:t}^{-1}\begin{bmatrix} -1\\0\\0\\ \end{bmatrix}=[la,lb,lc]Rs:t?1?????100????
其中?f?p~st\frac{\partial f}{\partial {\widetilde p}_{st}}?p?st??f?為梯度方向,對應直線的垂線方向和平面法向量;ptp_tpt?為當前點。
至此,與代碼里的arx、ary、arz、atx、aty、atz計算一致。

附錄:
旋轉矩陣偏導?Rs:t?1?rx\frac{\partial R_{s:t}^{-1}}{\partial rx }?rx?Rs:t?1??計算:
?Rs:t?1?rx=?Rzxy?rx\frac{\partial R_{s:t}^{-1}}{\partial rx }=\frac{\partial R_{zxy}}{\partial rx}?rx?Rs:t?1??=?rx?Rzxy??=?[cry?crz?srx?sry?srzcry?srz+srx?sry?crz?sry?crx?crx?srzcrx?crzsrxsry?crz+srx?cry?srzsry?srz?srx?cry?crzcry?crx]?rx=\frac {\partial \begin{bmatrix} cry*crz-srx*sry*srz& cry*srz+srx*sry*crz& -sry*crx\\ -crx*srz& crx*crz& srx\\ sry*crz+srx*cry*srz& sry*srz-srx*cry*crz& cry*crx \end{bmatrix}} {\partial rx}=?rx????cry?crz?srx?sry?srz?crx?srzsry?crz+srx?cry?srz?cry?srz+srx?sry?crzcrx?crzsry?srz?srx?cry?crz??sry?crxsrxcry?crx?????=[?crx?sry?srzcrx?sry?crzsrx?srysrx?srz?srx?crzcrxcrx?cry?srz?crx?cry?crz?cry?srx]=\begin{bmatrix} -crx*sry*srz& crx*sry*crz& srx*sry\\ srx*srz& -srx*crz& crx\\ crx*cry*srz& -crx*cry*crz& -cry*srx \end{bmatrix} =????crx?sry?srzsrx?srzcrx?cry?srz?crx?sry?crz?srx?crz?crx?cry?crz?srx?srycrx?cry?srx????
旋轉矩陣偏導?Rs:t?1?ry\frac{\partial R_{s:t}^{-1}}{\partial ry }?ry?Rs:t?1??計算:
?Rs:t?1?ry=?Rzxy?ry\frac{\partial R_{s:t}^{-1}}{\partial ry }=\frac{\partial R_{zxy}}{\partial ry}?ry?Rs:t?1??=?ry?Rzxy??=?[cry?crz?srx?sry?srzcry?srz+srx?sry?crz?sry?crx?crx?srzcrx?crzsrxsry?crz+srx?cry?srzsry?srz?srx?cry?crzcry?crx]?ry=\frac {\partial \begin{bmatrix} cry*crz-srx*sry*srz& cry*srz+srx*sry*crz& -sry*crx\\ -crx*srz& crx*crz& srx\\ sry*crz+srx*cry*srz& sry*srz-srx*cry*crz& cry*crx \end{bmatrix}} {\partial ry}=?ry????cry?crz?srx?sry?srz?crx?srzsry?crz+srx?cry?srz?cry?srz+srx?sry?crzcrx?crzsry?srz?srx?cry?crz??sry?crxsrxcry?crx?????=[?sry?crz?srx?cry?srz?sry?srz+srx?cry?crz?cry?crx000cry?crz?srx?sry?srzsry?srz+srx?sry?crz?sry?crx]=\begin{bmatrix} -sry*crz-srx*cry*srz& -sry*srz+srx*cry*crz& -cry*crx \\ 0& 0& 0\\ cry*crz-srx*sry*srz& sry*srz+srx*sry*crz& -sry*crx \end{bmatrix} =????sry?crz?srx?cry?srz0cry?crz?srx?sry?srz??sry?srz+srx?cry?crz0sry?srz+srx?sry?crz??cry?crx0?sry?crx????
旋轉矩陣偏導?Rs:t?1?rz\frac{\partial R_{s:t}^{-1}}{\partial rz }?rz?Rs:t?1??計算:
?Rs:t?1?ry=?Rzxy?rz\frac{\partial R_{s:t}^{-1}}{\partial ry }=\frac{\partial R_{zxy}}{\partial rz}?ry?Rs:t?1??=?rz?Rzxy??=?[cry?crz?srx?sry?srzcry?srz+srx?sry?crz?sry?crx?crx?srzcrx?crzsrxsry?crz+srx?cry?srzsry?srz?srx?cry?crzcry?crx]?rz=\frac {\partial \begin{bmatrix} cry*crz-srx*sry*srz& cry*srz+srx*sry*crz& -sry*crx\\ -crx*srz& crx*crz& srx\\ sry*crz+srx*cry*srz& sry*srz-srx*cry*crz& cry*crx \end{bmatrix}} {\partial rz}=?rz????cry?crz?srx?sry?srz?crx?srzsry?crz+srx?cry?srz?cry?srz+srx?sry?crzcrx?crzsry?srz?srx?cry?crz??sry?crxsrxcry?crx?????=[?cry?srz?srx?sry?crzcry?crz?srx?sry?srz0?crx?crz?crx?srz0?sry?srz?srx?cry?crzsry?crz+srx?cry?srz0]=\begin{bmatrix} -cry*srz-srx*sry*crz& cry*crz-srx*sry*srz& 0 \\ -crx*crz& -crx*srz& 0\\ -sry*srz-srx*cry*crz& sry*crz+srx*cry*srz& 0 \end{bmatrix} =????cry?srz?srx?sry?crz?crx?crz?sry?srz?srx?cry?crz?cry?crz?srx?sry?srz?crx?srzsry?crz+srx?cry?srz?000????

二、LOAM的LiDAR里程計代碼分析

主要是兩部分:運動補償和幀間配準。

  • 利用相鄰兩幀的點云數據進行配準,即完成ttt時刻和t+1t+1t+1時刻點云數據的關聯,并估計LiDAR的相對運動關系。
  • 配準工作需要基于邊緣點特征、平面特征點云進行:利用scanRegistration分別獲得ttt時刻和t+1t+1t+1時刻點云中的特征點,然后建立這兩部分點云的一一對應關系。

一些細節:

  • 每幀激光都會參與(所以幀率同VLP16的掃描幀率,10hz)
  • 通過對每一幀激光的配準,可以得到一個精度較差的odom;
  • 幀間匹配的初始pose可以由IMU得到
  • 若沒有IMU的時候由勻速運動模型得到

1、ROS訂閱和發布

先來看看main函數里怎么寫的。

int main(int argc, char** argv)
{ros::init(argc, argv, "laserOdometry");ros::NodeHandle nh;ros::Subscriber subCornerPointsSharp = nh.subscribe<sensor_msgs::PointCloud2>("/laser_cloud_sharp", 2, laserCloudSharpHandler);ros::Subscriber subCornerPointsLessSharp = nh.subscribe<sensor_msgs::PointCloud2>("/laser_cloud_less_sharp", 2, laserCloudLessSharpHandler);ros::Subscriber subSurfPointsFlat = nh.subscribe<sensor_msgs::PointCloud2>("/laser_cloud_flat", 2, laserCloudFlatHandler);ros::Subscriber subSurfPointsLessFlat = nh.subscribe<sensor_msgs::PointCloud2>("/laser_cloud_less_flat", 2, laserCloudLessFlatHandler);ros::Subscriber subLaserCloudFullRes = nh.subscribe<sensor_msgs::PointCloud2> ("/velodyne_cloud_2", 2, laserCloudFullResHandler);ros::Subscriber subImuTrans = nh.subscribe<sensor_msgs::PointCloud2> ("/imu_trans", 5, imuTransHandler);ros::Publisher pubLaserCloudCornerLast = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_corner_last", 2);ros::Publisher pubLaserCloudSurfLast = nh.advertise<sensor_msgs::PointCloud2>("/laser_cloud_surf_last", 2);ros::Publisher pubLaserCloudFullRes = nh.advertise<sensor_msgs::PointCloud2> ("/velodyne_cloud_3", 2);ros::Publisher pubLaserOdometry = nh.advertise<nav_msgs::Odometry> ("/laser_odom_to_init", 5);nav_msgs::Odometry laserOdometry;laserOdometry.header.frame_id = "/camera_init";laserOdometry.child_frame_id = "/laser_odom";tf::TransformBroadcaster tfBroadcaster;tf::StampedTransform laserOdometryTrans;laserOdometryTrans.frame_id_ = "/camera_init";laserOdometryTrans.child_frame_id_ = "/laser_odom";std::vector<int> pointSearchInd;//搜索到的點序std::vector<float> pointSearchSqDis;//搜索到的點平方距離PointType pointOri, pointSel/*選中的特征點*/, tripod1, tripod2, tripod3/*特征點的對應點*/, pointProj/*unused*/, coeff;//退化標志bool isDegenerate = false;//P矩陣,預測矩陣cv::Mat matP(6, 6, CV_32F, cv::Scalar::all(0));int frameCount = skipFrameNum;ros::Rate rate(100);bool status = ros::ok();while (status) {ros::spinOnce();if (newCornerPointsSharp && newCornerPointsLessSharp && newSurfPointsFlat && newSurfPointsLessFlat && newLaserCloudFullRes && newImuTrans &&fabs(timeCornerPointsSharp - timeSurfPointsLessFlat) < 0.005 &&fabs(timeCornerPointsLessSharp - timeSurfPointsLessFlat) < 0.005 &&fabs(timeSurfPointsFlat - timeSurfPointsLessFlat) < 0.005 &&fabs(timeLaserCloudFullRes - timeSurfPointsLessFlat) < 0.005 &&fabs(timeImuTrans - timeSurfPointsLessFlat) < 0.005) {  //同步作用,確保同時收到同一個點云的特征點以及IMU信息才進入newCornerPointsSharp = false;newCornerPointsLessSharp = false;newSurfPointsFlat = false;newSurfPointsLessFlat = false;newLaserCloudFullRes = false;newImuTrans = false;/***** 一、初始化 *****//***** 二、點云處理 *****//***** 三、坐標轉換 *****/}}

訂閱器 :訂閱scanRegistration節點發布的消息并從ROS::Msg類型轉換成程序可以處理的pcl點云類型;

  • subCornerPointsSharp 訂閱 /laser_cloud_sharp 調用laserCloudSharpHandler
  • subCornerPointsLessSharp 訂閱 /laser_cloud_less_sharp 調用laserCloudLessSharpHandler
  • subSurfPointsFlat 訂閱 pubSurfPointFlat 調用 laserCloudFlatHandler
  • subSurfPointLessFlat 訂閱 pubSurfPointLessFlat 調用 laserCloudLessFlatHandler
  • subLaserCloudFullRes 訂閱 /velodyne_cloud_2 調用laserCloudFullResHandler 處理全部點云數據
  • subImuTrans 訂閱 /imu_trans 調用imuTransHandler 處理IMU數據

發布器 :其中/laser_odom_to_init消息的發布頻率高,其余三個消息每接收到三次scanRegistration節點的消息才發布一次。

  • pubLaserCloudCornerLast 發布 /laser_cloud_corner_last
  • pubLaserCloudSurfLast 發布 /laser_cloud_surf_last
  • pubLaserCloudFullRes 發布 /velodyne_cloud_3
  • pubLaserOdometry 發布 /laser_odom_to_init

總體計算過程分為三步:初始化、點云處理、坐標轉換。下面一步一步來

2、初始化

       /********* Initialization ********///將第一個點云數據集發送給laserMapping,從下一個點云數據開始處理if (!systemInited) {//將cornerPointsLessSharp與laserCloudCornerLast交換,目的保存cornerPointsLessSharp的值下輪使用pcl::PointCloud<PointType>::Ptr laserCloudTemp = cornerPointsLessSharp;cornerPointsLessSharp = laserCloudCornerLast;laserCloudCornerLast = laserCloudTemp;//將surfPointLessFlat與laserCloudSurfLast交換,目的保存surfPointsLessFlat的值下輪使用laserCloudTemp = surfPointsLessFlat;surfPointsLessFlat = laserCloudSurfLast;laserCloudSurfLast = laserCloudTemp;//使用上一幀的特征點構建kd-treekdtreeCornerLast->setInputCloud(laserCloudCornerLast);//所有的邊沿點集合kdtreeSurfLast->setInputCloud(laserCloudSurfLast);//所有的平面點集合//將cornerPointsLessSharp和surfPointLessFlat點也即邊沿點和平面點分別發送給laserMappingsensor_msgs::PointCloud2 laserCloudCornerLast2;pcl::toROSMsg(*laserCloudCornerLast, laserCloudCornerLast2);laserCloudCornerLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);laserCloudCornerLast2.header.frame_id = "/camera";pubLaserCloudCornerLast.publish(laserCloudCornerLast2);sensor_msgs::PointCloud2 laserCloudSurfLast2;pcl::toROSMsg(*laserCloudSurfLast, laserCloudSurfLast2);laserCloudSurfLast2.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);laserCloudSurfLast2.header.frame_id = "/camera";pubLaserCloudSurfLast.publish(laserCloudSurfLast2);//記住原點的翻滾角和俯仰角transformSum[0] += imuPitchStart;transformSum[2] += imuRollStart;systemInited = true;continue;}//T平移量的初值賦值為加減速的位移量,為其梯度下降的方向(沿用上次轉換的T(一個sweep勻速模型),同時在其基礎上減去勻速運動位移,即只考慮加減速的位移量)transform[3] -= imuVeloFromStartX * scanPeriod;transform[4] -= imuVeloFromStartY * scanPeriod;transform[5] -= imuVeloFromStartZ * scanPeriod;/**********************************************/

主要是等待下一時刻的點云再做處理。

3、點云處理——點云配準與運動估計

這部分是整個laserOdometry節點的重中之重。假設你現在已經得到了兩坨點云,對他們進行處理之前你首先得保證這些特征點足夠多,否則你帶了兩坨沒有任何特征的點,那可就真的愛莫能助了,用程序表達就是設定一個閾值進行判斷。

在點云足夠多的條件下,終于要開始正式工作了。這里我們設定整個L-M運動估計的迭代次數為25次,以保證運算效率。迭代部分又可分為:對特征邊/面上的點進行處理,構建Jaccobian矩陣,L-M運動估計求解。

      if (laserCloudCornerLastNum > 10 && laserCloudSurfLastNum > 100) {std::vector<int> indices;pcl::removeNaNFromPointCloud(*cornerPointsSharp,*cornerPointsSharp, indices);int cornerPointsSharpNum = cornerPointsSharp->points.size();int surfPointsFlatNum = surfPointsFlat->points.size();//Levenberg-Marquardt算法(L-M method),非線性最小二乘算法,最優化算法的一種//最多迭代25次for (int iterCount = 0; iterCount < 25; iterCount++) {laserCloudOri->clear();coeffSel->clear();/***** 1. 邊緣特征上的點配準并構建Jaccobian *****//***** 2. 平面特征上的點配準并構建Jaccobian  *****//***** 3. L-M運動估計求解 *****/}}

代碼中是使用Gauss-Newton優化(相比傳統的GN法,代碼中增加了一個阻尼因子,代碼中的s),這里關鍵在于如何把點云配準和運動估計的問題轉換為優化求解的問題。
主要思路:

  1. 構建約束方程
  2. 約束方程求偏導構建Jaccobian矩陣
  3. 求解

下面再一步一步來看:關于構建約束方程的問題就是這節標題中提到的點云配準的問題,其基本思想就是從上一幀點云中找到一些邊/面特征點,在當前幀點云中同樣找這么一些點,建立他們之間的約束關系。

3.1、邊緣特征上的點配準

          /* 邊緣特征匹配 *///處理當前點云中的曲率最大的特征點,從上個點云中曲率比較大的特征點中找兩個最近距離點,一個點使用kd-tree查找,另一個根據找到的點在其相鄰線找另外一個最近距離的點for (int i = 0; i < cornerPointsSharpNum; i++){TransformToStart(&cornerPointsSharp->points[i], &pointSel);//每迭代五次,重新查找最近點if (iterCount % 5 == 0){std::vector<int> indices;pcl::removeNaNFromPointCloud(*laserCloudCornerLast,*laserCloudCornerLast, indices);//kd-tree查找一個最近距離點,邊沿點未經過體素柵格濾波,一般邊沿點本來就比較少,不做濾波kdtreeCornerLast->nearestKSearch(pointSel, 1, pointSearchInd, pointSearchSqDis);int closestPointInd = -1, minPointInd2 = -1;//尋找相鄰線距離目標點距離最小的點//再次提醒:velodyne是2度一線,scanID相鄰并不代表線號相鄰,相鄰線度數相差2度,也即線號scanID相差2if (pointSearchSqDis[0] < 25){//找到的最近點距離的確很近的話closestPointInd = pointSearchInd[0];//提取最近點線號int closestPointScan = int(laserCloudCornerLast->points[closestPointInd].intensity);float pointSqDis, minPointSqDis2 = 25;//初始門檻值5米,可大致過濾掉scanID相鄰,但實際線不相鄰的值//尋找距離目標點最近距離的平方和最小的點for (int j = closestPointInd + 1; j < cornerPointsSharpNum; j++){//向scanID增大的方向查找if (int(laserCloudCornerLast->points[j].intensity) > closestPointScan + 2.5){//非相鄰線break;}pointSqDis = (laserCloudCornerLast->points[j].x - pointSel.x) * (laserCloudCornerLast->points[j].x - pointSel.x) + (laserCloudCornerLast->points[j].y - pointSel.y) * (laserCloudCornerLast->points[j].y - pointSel.y) + (laserCloudCornerLast->points[j].z - pointSel.z) * (laserCloudCornerLast->points[j].z - pointSel.z);if (int(laserCloudCornerLast->points[j].intensity) > closestPointScan){//確保兩個點不在同一條scan上(相鄰線查找應該可以用scanID == closestPointScan +/- 1 來做)if (pointSqDis < minPointSqDis2){//距離更近,要小于初始值5米//更新最小距離與點序minPointSqDis2 = pointSqDis;minPointInd2 = j;}}}//同理for (int j = closestPointInd - 1; j >= 0; j--) {//向scanID減小的方向查找if (int(laserCloudCornerLast->points[j].intensity) < closestPointScan - 2.5){break;}pointSqDis = (laserCloudCornerLast->points[j].x - pointSel.x) * (laserCloudCornerLast->points[j].x - pointSel.x) + (laserCloudCornerLast->points[j].y - pointSel.y) * (laserCloudCornerLast->points[j].y - pointSel.y) + (laserCloudCornerLast->points[j].z - pointSel.z) * (laserCloudCornerLast->points[j].z - pointSel.z);if (int(laserCloudCornerLast->points[j].intensity) < closestPointScan){if (pointSqDis < minPointSqDis2){minPointSqDis2 = pointSqDis;minPointInd2 = j;}}}}//記住組成線的點序pointSearchCornerInd1[i] = closestPointInd;//kd-tree最近距離點,-1表示未找到滿足的點pointSearchCornerInd2[i] = minPointInd2;//另一個最近的,-1表示未找到滿足的點}if (pointSearchCornerInd2[i] >= 0){//大于等于0,不等于-1,說明兩個點都找到了tripod1 = laserCloudCornerLast->points[pointSearchCornerInd1[i]];tripod2 = laserCloudCornerLast->points[pointSearchCornerInd2[i]];//選擇的特征點記為O,kd-tree最近距離點記為A,另一個最近距離點記為Bfloat x0 = pointSel.x;float y0 = pointSel.y;float z0 = pointSel.z;float x1 = tripod1.x;float y1 = tripod1.y;float z1 = tripod1.z;float x2 = tripod2.x;float y2 = tripod2.y;float z2 = tripod2.z;//向量OA = (x0 - x1, y0 - y1, z0 - z1), 向量OB = (x0 - x2, y0 - y2, z0 - z2),向量AB = (x1 - x2, y1 - y2, z1 - z2)//向量OA OB的向量積(即叉乘)為://|  i      j      k  |//|x0-x1  y0-y1  z0-z1|//|x0-x2  y0-y2  z0-z2|//模為:float a012 = sqrt(((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))* ((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))+ ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))* ((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))+ ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))* ((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1)));//兩個最近距離點之間的距離,即向量AB的模float l12 = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + (z1 - z2)*(z1 - z2));//點到線的距離,d = |向量OA 叉乘 向量OB|/|AB|float ld2 = a012 / l12;//AB方向的單位向量與OAB平面的單位法向量的向量積在各軸上的分量(d的方向)//x軸分量ifloat la = ((y1 - y2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))+ (z1 - z2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))) / a012 / l12;//y軸分量jfloat lb = -((x1 - x2)*((x0 - x1)*(y0 - y2) - (x0 - x2)*(y0 - y1))- (z1 - z2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;//z軸分量kfloat lc = -((x1 - x2)*((x0 - x1)*(z0 - z2) - (x0 - x2)*(z0 - z1))+ (y1 - y2)*((y0 - y1)*(z0 - z2) - (y0 - y2)*(z0 - z1))) / a012 / l12;//unusedpointProj = pointSel;pointProj.x -= la * ld2;pointProj.y -= lb * ld2;pointProj.z -= lc * ld2;//權重計算,距離越大權重越小,距離越小權重越大,得到的權重范圍<=1float s = 1;if (iterCount >= 5){//5次迭代之后開始增加權重因素 fabs返回 x 的絕對值s = 1 - 1.8 * fabs(ld2);}//考慮權重coeff.x = s * la;coeff.y = s * lb;coeff.z = s * lc;coeff.intensity = s * ld2;if (s > 0.1 && ld2 != 0){//只保留權重大的,也即距離比較小的點,同時也舍棄距離為零的laserCloudOri->push_back(cornerPointsSharp->points[i]);coeffSel->push_back(coeff);}}}

3.2、平面特征上的點配準

          /* 平面特征匹配 *///對本次接收到的曲率最小的點,從上次接收到的點云曲率比較小的點中找三點組成平面;1、一個使用kd-tree查找;2、另外一個在同一線上查找滿足要求的;3、第三個在不同線上查找滿足要求的for (int i = 0; i < surfPointsFlatNum; i++){TransformToStart(&surfPointsFlat->points[i], &pointSel);if (iterCount % 5 == 0){//kd-tree最近點查找,在經過體素柵格濾波之后的平面點中查找,一般平面點太多,濾波后最近點查找數據量小kdtreeSurfLast->nearestKSearch(pointSel, 1, pointSearchInd, pointSearchSqDis);int closestPointInd = -1, minPointInd2 = -1, minPointInd3 = -1;if (pointSearchSqDis[0] < 25){closestPointInd = pointSearchInd[0];int closestPointScan = int(laserCloudSurfLast->points[closestPointInd].intensity);float pointSqDis, minPointSqDis2 = 25, minPointSqDis3 = 25;for (int j = closestPointInd + 1; j < surfPointsFlatNum; j++){if (int(laserCloudSurfLast->points[j].intensity) > closestPointScan + 2.5){break;}pointSqDis = (laserCloudSurfLast->points[j].x - pointSel.x) *(laserCloudSurfLast->points[j].x - pointSel.x) +(laserCloudSurfLast->points[j].y - pointSel.y) *(laserCloudSurfLast->points[j].y - pointSel.y) +(laserCloudSurfLast->points[j].z - pointSel.z) *(laserCloudSurfLast->points[j].z - pointSel.z);if (int(laserCloudSurfLast->points[j].intensity) <= closestPointScan){//如果點的線號小于等于最近點的線號(應該最多取等,也即同一線上的點)if (pointSqDis < minPointSqDis2){minPointSqDis2 = pointSqDis;minPointInd2 = j;}}else{//如果點處在大于該線上if (pointSqDis < minPointSqDis3){minPointSqDis3 = pointSqDis;minPointInd3 = j;}}}//同理for (int j = closestPointInd - 1; j >= 0; j--){if (int(laserCloudSurfLast->points[j].intensity) < closestPointScan - 2.5){break;}pointSqDis = (laserCloudSurfLast->points[j].x - pointSel.x) *(laserCloudSurfLast->points[j].x - pointSel.x) +(laserCloudSurfLast->points[j].y - pointSel.y) *(laserCloudSurfLast->points[j].y - pointSel.y) +(laserCloudSurfLast->points[j].z - pointSel.z) *(laserCloudSurfLast->points[j].z - pointSel.z);if (int(laserCloudSurfLast->points[j].intensity) >= closestPointScan){if (pointSqDis < minPointSqDis2){minPointSqDis2 = pointSqDis;minPointInd2 = j;}}else{if (pointSqDis < minPointSqDis3){minPointSqDis3 = pointSqDis;minPointInd3 = j;}}}}pointSearchSurfInd1[i] = closestPointInd;//kd-tree最近距離點,-1表示未找到滿足要求的點pointSearchSurfInd2[i] = minPointInd2;//同一線號上的距離最近的點,-1表示未找到滿足要求的點pointSearchSurfInd3[i] = minPointInd3;//不同線號上的距離最近的點,-1表示未找到滿足要求的點}if (pointSearchSurfInd2[i] >= 0 && pointSearchSurfInd3[i] >= 0){//找到了三個點tripod1 = laserCloudSurfLast->points[pointSearchSurfInd1[i]];//A點tripod2 = laserCloudSurfLast->points[pointSearchSurfInd2[i]];//B點tripod3 = laserCloudSurfLast->points[pointSearchSurfInd3[i]];//C點//向量AB = (tripod2.x - tripod1.x, tripod2.y - tripod1.y, tripod2.z - tripod1.z)//向量AC = (tripod3.x - tripod1.x, tripod3.y - tripod1.y, tripod3.z - tripod1.z)//向量AB AC的向量積(即叉乘),得到的是法向量//x軸方向分向量ifloat pa = (tripod2.y - tripod1.y) * (tripod3.z - tripod1.z) - (tripod3.y - tripod1.y) * (tripod2.z - tripod1.z);//y軸方向分向量jfloat pb = (tripod2.z - tripod1.z) * (tripod3.x - tripod1.x) - (tripod3.z - tripod1.z) * (tripod2.x - tripod1.x);//z軸方向分向量kfloat pc = (tripod2.x - tripod1.x) * (tripod3.y - tripod1.y) - (tripod3.x - tripod1.x) * (tripod2.y - tripod1.y);float pd = -(pa * tripod1.x + pb * tripod1.y + pc * tripod1.z);//法向量的模float ps = sqrt(pa * pa + pb * pb + pc * pc);//pa pb pc為法向量各方向上的單位向量pa /= ps;pb /= ps;pc /= ps;pd /= ps;//點到面的距離:向量OA與與法向量的點積除以法向量的模float pd2 = pa * pointSel.x + pb * pointSel.y + pc * pointSel.z + pd;//unusedpointProj = pointSel;pointProj.x -= pa * pd2;pointProj.y -= pb * pd2;pointProj.z -= pc * pd2;//同理計算權重float s = 1;if (iterCount >= 5){s = 1 - 1.8 * fabs(pd2) / sqrt(sqrt(pointSel.x * pointSel.x+ pointSel.y * pointSel.y + pointSel.z * pointSel.z));}//考慮權重coeff.x = s * pa;coeff.y = s * pb;coeff.z = s * pc;coeff.intensity = s * pd2;if (s > 0.1 && pd2 != 0) {//保存原始點與相應的系數laserCloudOri->push_back(surfPointsFlat->points[i]);coeffSel->push_back(coeff);}}}

3.3、構建Jaccobian并進行運動估計求解

根據上一部分推導的公式,我們有了這兩坨點云的約束方程,構建Jaccobian矩陣就是直接對待估參數X~(k,i)L{\widetilde X}_{(k,i)}^{\boldsymbol L}X(k,i)L?求偏導了。
再看對應程序中如何對應的:
arx=?f?rx,ary=?f?ry,arz=?f?rzarx=\frac{\partial f}{\partial rx },ary=\frac{\partial f}{\partial ry },arz=\frac{\partial f}{\partial rz }arx=?rx?f?,ary=?ry?f?,arz=?rz?f?atx=?f?tx,aty=?f?ty,atz=?f?tzatx=\frac{\partial f}{\partial tx },aty=\frac{\partial f}{\partial ty },atz=\frac{\partial f}{\partial tz }atx=?tx?f?,aty=?ty?f?,atz=?tz?f?
以arxarxarx為例:
arx=?f?rx=[la,lb,lc]?Rs:t?1?rx[pxpypz]?[la,lb,lc]?Rs:t?1?rx[txtytz]arx=\frac{\partial f}{\partial rx }=[la,lb,lc]\frac{\partial R_{s:t}^{-1}}{\partial rx} \begin{bmatrix} px\\py\\pz\\ \end{bmatrix}-[la,lb,lc]\frac{\partial R_{s:t}^{-1}}{\partial rx}\begin{bmatrix} tx\\ty\\tz\\ \end{bmatrix}arx=?rx?f?=[la,lb,lc]?rx?Rs:t?1?????pxpypz?????[la,lb,lc]?rx?Rs:t?1?????txtytz????=[lalblc][?crx?sry?srzcrx?sry?crzsrx?srysrx?srz?srx?crzcrxcrx?cry?srz?crx?cry?crz?cry?srx][px?txpy?typz?tz]=\begin{bmatrix} la& lb& lc \end{bmatrix} \begin{bmatrix} -crx*sry*srz& crx*sry*crz& srx*sry\\ srx*srz& -srx*crz& crx\\ crx*cry*srz& -crx*cry*crz& -cry*srx \end{bmatrix} \begin{bmatrix} px-tx\\ py-ty\\ pz-tz \end{bmatrix}=[la?lb?lc?]????crx?sry?srzsrx?srzcrx?cry?srz?crx?sry?crz?srx?crz?crx?cry?crz?srx?srycrx?cry?srx???????px?txpy?typz?tz????
=(?crx?sry?srz?px+crx?crz?sry?py+srx?sry?pz=(-crx*sry*srz*px + crx*crz*sry*py + srx*sry*pz=(?crx?sry?srz?px+crx?crz?sry?py+srx?sry?pz
+tx?crx?sry?srz?ty?crx?crz?sry?tz?srx?sry)?la+ tx*crx*sry*srz - ty*crx*crz*sry - tz*srx*sry) * la+tx?crx?sry?srz?ty?crx?crz?sry?tz?srx?sry)?la
+(srx?srz?px?crz?srx?py+crx?pz+ (srx*srz*px - crz*srx*py + crx*pz+(srx?srz?px?crz?srx?py+crx?pz
+ty?crz?srx?tz?crx?tx?srx?srz)?lb+ ty*crz*srx - tz*crx - tx*srx*srz) * lb+ty?crz?srx?tz?crx?tx?srx?srz)?lb
+(crx?cry?srz?px?crx?cry?crz?py?cry?srx?pz+(crx*cry*srz*px - crx*cry*crz*py - cry*srx*pz+(crx?cry?srz?px?crx?cry?crz?py?cry?srx?pz
+tz?cry?srx+ty?crx?cry?crz?tx?crx?cry?srz)?lc+ tz*cry*srx + ty*crx*cry*crz - tx*crx*cry*srz) * lc+tz?cry?srx+ty?crx?cry?crz?tx?crx?cry?srz)?lc

          int pointSelNum = laserCloudOri->points.size();//滿足要求的特征點至少10個,特征匹配數量太少棄用此幀數據if (pointSelNum < 10){continue;}/* LM優化過程 QR分解求解T向量*/cv::Mat matA(pointSelNum, 6, CV_32F, cv::Scalar::all(0));cv::Mat matAt(6, pointSelNum, CV_32F, cv::Scalar::all(0));cv::Mat matAtA(6, 6, CV_32F, cv::Scalar::all(0));cv::Mat matB(pointSelNum, 1, CV_32F, cv::Scalar::all(0));cv::Mat matAtB(6, 1, CV_32F, cv::Scalar::all(0));cv::Mat matX(6, 1, CV_32F, cv::Scalar::all(0));//計算matA,matB矩陣for (int i = 0; i < pointSelNum; i++){pointOri = laserCloudOri->points[i];coeff = coeffSel->points[i];float s = 1;float srx = sin(s * transform[0]);float crx = cos(s * transform[0]);float sry = sin(s * transform[1]);float cry = cos(s * transform[1]);float srz = sin(s * transform[2]);float crz = cos(s * transform[2]);float tx = s * transform[3];float ty = s * transform[4];float tz = s * transform[5];float arx = (-s*crx*sry*srz*pointOri.x + s*crx*crz*sry*pointOri.y + s*srx*sry*pointOri.z+ s*tx*crx*sry*srz - s*ty*crx*crz*sry - s*tz*srx*sry) * coeff.x+ (s*srx*srz*pointOri.x - s*crz*srx*pointOri.y + s*crx*pointOri.z+ s*ty*crz*srx - s*tz*crx - s*tx*srx*srz) * coeff.y+ (s*crx*cry*srz*pointOri.x - s*crx*cry*crz*pointOri.y - s*cry*srx*pointOri.z+ s*tz*cry*srx + s*ty*crx*cry*crz - s*tx*crx*cry*srz) * coeff.z;float ary = ((-s*crz*sry - s*cry*srx*srz)*pointOri.x+ (s*cry*crz*srx - s*sry*srz)*pointOri.y - s*crx*cry*pointOri.z+ tx*(s*crz*sry + s*cry*srx*srz) + ty*(s*sry*srz - s*cry*crz*srx)+ s*tz*crx*cry) * coeff.x+ ((s*cry*crz - s*srx*sry*srz)*pointOri.x+ (s*cry*srz + s*crz*srx*sry)*pointOri.y - s*crx*sry*pointOri.z+ s*tz*crx*sry - ty*(s*cry*srz + s*crz*srx*sry)- tx*(s*cry*crz - s*srx*sry*srz)) * coeff.z;float arz = ((-s*cry*srz - s*crz*srx*sry)*pointOri.x + (s*cry*crz - s*srx*sry*srz)*pointOri.y+ tx*(s*cry*srz + s*crz*srx*sry) - ty*(s*cry*crz - s*srx*sry*srz)) * coeff.x+ (-s*crx*crz*pointOri.x - s*crx*srz*pointOri.y+ s*ty*crx*srz + s*tx*crx*crz) * coeff.y+ ((s*cry*crz*srx - s*sry*srz)*pointOri.x + (s*crz*sry + s*cry*srx*srz)*pointOri.y+ tx*(s*sry*srz - s*cry*crz*srx) - ty*(s*crz*sry + s*cry*srx*srz)) * coeff.z;float atx = -s*(cry*crz - srx*sry*srz) * coeff.x + s*crx*srz * coeff.y- s*(crz*sry + cry*srx*srz) * coeff.z;float aty = -s*(cry*srz + crz*srx*sry) * coeff.x - s*crx*crz * coeff.y- s*(sry*srz - cry*crz*srx) * coeff.z;float atz = s*crx*sry * coeff.x - s*srx * coeff.y - s*crx*cry * coeff.z;float d2 = coeff.intensity;matA.at<float>(i, 0) = arx;matA.at<float>(i, 1) = ary;matA.at<float>(i, 2) = arz;matA.at<float>(i, 3) = atx;matA.at<float>(i, 4) = aty;matA.at<float>(i, 5) = atz;matB.at<float>(i, 0) = -0.05 * d2;}cv::transpose(matA, matAt);matAtA = matAt * matA;matAtB = matAt * matB;//求解matAtA * matX = matAtBcv::solve(matAtA, matAtB, matX, cv::DECOMP_QR);if (iterCount == 0){//特征值1*6矩陣 Mat(int rows, int cols, int type, const Scalar& s)cv::Mat matE(1, 6, CV_32F, cv::Scalar::all(0));//特征向量6*6矩陣cv::Mat matV(6, 6, CV_32F, cv::Scalar::all(0));cv::Mat matV2(6, 6, CV_32F, cv::Scalar::all(0));//求解特征值/特征向量cv::eigen(matAtA, matE, matV);matV.copyTo(matV2);isDegenerate = false;//特征值取值門檻float eignThre[6] = {10, 10, 10, 10, 10, 10};for (int i = 5; i >= 0; i--){//從小到大查找if (matE.at<float>(0, i) < eignThre[i]){//特征值太小,則認為處在兼并環境中,發生了退化for (int j = 0; j < 6; j++) {//對應的特征向量置為0matV2.at<float>(i, j) = 0;}isDegenerate = true;}else{break;}}//計算P矩陣matP = matV.inv() * matV2;}if (isDegenerate){//如果發生退化,只使用預測矩陣P計算cv::Mat matX2(6, 1, CV_32F, cv::Scalar::all(0));matX.copyTo(matX2);matX = matP * matX2;}//累加每次迭代的旋轉平移量transform[0] += matX.at<float>(0, 0);transform[1] += matX.at<float>(1, 0);transform[2] += matX.at<float>(2, 0);transform[3] += matX.at<float>(3, 0);transform[4] += matX.at<float>(4, 0);transform[5] += matX.at<float>(5, 0);for(int i=0; i<6; i++){if(isnan(transform[i]))//判斷是否非數字transform[i]=0;}//計算旋轉平移量,如果很小就停止迭代float deltaR = sqrt(pow(rad2deg(matX.at<float>(0, 0)), 2) +pow(rad2deg(matX.at<float>(1, 0)), 2) +pow(rad2deg(matX.at<float>(2, 0)), 2));float deltaT = sqrt(pow(matX.at<float>(3, 0) * 100, 2) +pow(matX.at<float>(4, 0) * 100, 2) +pow(matX.at<float>(5, 0) * 100, 2));if (deltaR < 0.1 && deltaT < 0.1){//迭代終止條件跳出循環break;}

4、坐標轉換

計算出了兩坨點云間的相對運動,但他們是在這兩幀點云的局部坐標系下的,我們需要把它轉換到世界坐標系下,因此需要進行轉換。
這部分內容較為簡單,直接上代碼了:

      float rx, ry, rz, tx, ty, tz;//求相對于原點的旋轉量,垂直方向上1.05倍修正?AccumulateRotation(transformSum[0], transformSum[1], transformSum[2], -transform[0], -transform[1] * 1.05, -transform[2], rx, ry, rz);float x1 = cos(rz) * (transform[3] - imuShiftFromStartX) - sin(rz) * (transform[4] - imuShiftFromStartY);float y1 = sin(rz) * (transform[3] - imuShiftFromStartX) + cos(rz) * (transform[4] - imuShiftFromStartY);float z1 = transform[5] * 1.05 - imuShiftFromStartZ;float x2 = x1;float y2 = cos(rx) * y1 - sin(rx) * z1;float z2 = sin(rx) * y1 + cos(rx) * z1;//求相對于原點的平移量tx = transformSum[3] - (cos(ry) * x2 + sin(ry) * z2);ty = transformSum[4] - y2;tz = transformSum[5] - (-sin(ry) * x2 + cos(ry) * z2);//根據IMU修正旋轉量PluginIMURotation(rx, ry, rz, imuPitchStart, imuYawStart, imuRollStart, imuPitchLast, imuYawLast, imuRollLast, rx, ry, rz);//得到世界坐標系下的轉移矩陣transformSum[0] = rx;transformSum[1] = ry;transformSum[2] = rz;transformSum[3] = tx;transformSum[4] = ty;transformSum[5] = tz;//歐拉角轉換成四元數geometry_msgs::Quaternion geoQuat = tf::createQuaternionMsgFromRollPitchYaw(rz, -rx, -ry);//publish四元數和平移量laserOdometry.header.stamp = ros::Time().fromSec(timeSurfPointsLessFlat);laserOdometry.pose.pose.orientation.x = -geoQuat.y;laserOdometry.pose.pose.orientation.y = -geoQuat.z;laserOdometry.pose.pose.orientation.z = geoQuat.x;laserOdometry.pose.pose.orientation.w = geoQuat.w;laserOdometry.pose.pose.position.x = tx;laserOdometry.pose.pose.position.y = ty;laserOdometry.pose.pose.position.z = tz;pubLaserOdometry.publish(laserOdometry);

至此我們接完成了整個laserOdometry的計算。

總結

以上是生活随笔為你收集整理的[笔记]三维激光SLAM学习——LiDAR里程计原理推导代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

韩国av不卡 | 国内精品久久久久久久久久久 | 久日精品| 国产91勾搭技师精品 | 免费在线观看av网址 | 亚洲国产中文在线观看 | 99久久99热这里只有精品 | 色偷偷88888欧美精品久久 | 99在线热播精品免费 | 婷婷在线不卡 | 日韩欧美一区二区在线播放 | 天天草综合网 | 国产精品免费小视频 | 97视频一区| 色.www | 日韩精品一区二区在线视频 | 波多野结衣在线观看一区 | 一级黄色片在线播放 | 欧美日韩亚洲精品在线 | 日本 在线 视频 中文 有码 | 亚洲综合在线五月天 | 中国一区二区视频 | 亚洲无毛专区 | 伊人网av | 特级西西444www高清大视频 | 久久精品一级片 | 欧美一级专区免费大片 | 久久精品国产精品亚洲 | 91丨九色丨丝袜 | 波多野结衣亚洲一区二区 | av中文字幕不卡 | www.91av在线| 免费视频色| 欧美大jb| 欧美极品xxx | 亚洲精品国产精品乱码在线观看 | 色多多污污在线观看 | 欧美精品久久人人躁人人爽 | 91网址在线看| 国产高清在线精品 | 999久久 | 欧美福利在线播放 | 91色一区二区三区 | 国产精品久久久久久久妇 | 久久精品最新 | 97精品国产97久久久久久久久久久久 | 国产黄色av网站 | 中文字幕韩在线第一页 | 9ⅰ精品久久久久久久久中文字幕 | 天天操偷偷干 | 日本午夜在线观看 | 久久久久久影视 | 欧美一区日韩一区 | 91精品婷婷国产综合久久蝌蚪 | 天天操夜| 久久久久一区二区三区四区 | 国产精品高潮在线观看 | 亚洲色图 校园春色 | 91精品国产欧美一区二区成人 | 99热亚洲精品 | 国产视频九色蝌蚪 | 国产精品99久久久久久久久久久久 | 亚洲精品456在线播放乱码 | 婷婷六月综合亚洲 | 欧美a视频 | 国产精品一区电影 | 日韩videos| 国产精品理论片 | 娇妻呻吟一区二区三区 | 亚洲 成人 欧美 | 国产在线黄色 | 国产视频1| 激情婷婷色 | 91亚洲在线 | 成人三级黄色 | 久久久久国产精品免费 | 99在线视频观看 | 草久久av| 在线а√天堂中文官网 | 国产美女网 | 综合网在线视频 | 日韩黄在线观看 | 国产精品女人久久久 | 超碰com| 国产成人精品av在线 | 2018好看的中文在线观看 | 天天综合网入口 | 国产精品porn | 亚洲精品人人 | 日本中文字幕影院 | 在线看片视频 | 亚洲欧美精品在线 | 就要干b| 午夜黄色一级片 | 久久久久国 | 久久久久久久国产精品影院 | 亚洲国产一区在线观看 | 成人中文字幕在线观看 | 人人超碰免费 | 日韩视频 一区 | www..com毛片| 开心激情综合网 | 丝袜美腿亚洲综合 | 在线免费黄网站 | 最近中文字幕mv免费高清在线 | 五月天高清欧美mv | 中文在线免费看视频 | 日韩欧美在线中文字幕 | 欧美激情视频一二三区 | 亚洲日本va午夜在线影院 | 午夜av电影院 | 久久爽久久爽久久av东京爽 | 最近中文字幕mv | 在线精品一区二区 | 中文字幕在线观看视频一区 | 欧美日韩一区二区在线观看 | 99久久99久久 | 欧女人精69xxxxxx | 久久久精品 一区二区三区 国产99视频在线观看 | 免费看黄网站在线 | 婷婷.com| 99成人免费视频 | 国产免费观看视频 | 国产精品一区二区在线 | 2019av在线视频| 亚洲1级片 | 国产做爰视频 | 欧美一区二区在线 | 日韩免费观看视频 | 久久新视频 | 婷婷在线视频 | 免费h漫在线观看 | 亚洲成人黄色 | 丁香 婷婷 激情 | 欧美午夜性生活 | 免费视频一二三 | 久日精品| 久久国产区 | 久久综合欧美精品亚洲一区 | 国内免费久久久久久久久久久 | 亚洲波多野结衣 | 久操中文字幕在线观看 | 国产一级电影免费观看 | 欧美一区二区三区四区夜夜大片 | 黄a在线| 婷婷www | 亚洲国产精品va在线看黑人 | 高清视频一区 | 国产精品免费大片视频 | 在线看国产日韩 | 免费看一及片 | 亚洲国产精品成人va在线观看 | 最近中文字幕在线 | 免费观看国产成人 | 国产精品第7页 | 久久综合桃花 | 91视频在线免费下载 | 久久爱资源网 | 欧美久久久久久久 | 久久无码av一区二区三区电影网 | 免费久久99精品国产婷婷六月 | 人成免费网站 | 久草精品视频在线观看 | 97超碰色偷偷 | 2019中文最近的2019中文在线 | 国内亚洲精品 | 久久久高清一区二区三区 | 在线日韩中文字幕 | 在线观看视频你懂的 | 人人狠狠综合久久亚洲婷 | 日日干夜夜草 | 伊人激情综合 | 99精品在线免费视频 | 成人亚洲网 | 人人操日日干 | 久久精品99视频 | 人人射人人插 | 9999精品免费视频 | 99精品免费久久久久久日本 | 久久超级碰| 成人性生交大片免费观看网站 | 99精品在线直播 | 成人av一区二区兰花在线播放 | 91成人免费看| 国产精品久久久久永久免费观看 | 日韩免费电影网站 | 国产精品久久久久久影院 | 久草在线99 | 国产中的精品av小宝探花 | 亚洲伊人色 | 久久亚洲国产精品 | 日韩超碰| 中文字幕在线有码 | 国产成人免费观看久久久 | 深夜福利视频一区二区 | 五月综合久久 | 麻豆视频在线观看免费 | 日韩免费一区二区在线观看 | 日日夜夜天天久久 | 五月婷婷在线观看视频 | 四虎成人精品永久免费av | 中文字幕资源网在线观看 | 国产又粗又猛又爽又黄的视频先 | 久久成人精品电影 | ,午夜性刺激免费看视频 | 99久久99久久 | 国产一区二区三区免费在线观看 | 久久婷婷国产色一区二区三区 | 日韩久久精品 | 婷婷视频导航 | 激情五月综合 | 日韩精品欧美专区 | 在线视频国产区 | 成人av免费网站 | 在线www色 | 最近中文字幕在线播放 | 三上悠亚在线免费 | 91九色国产视频 | 中文字幕电影在线 | 国产成人免费高清 | 国产成人三级在线播放 | 狠狠干中文字幕 | www五月天com | 国产尤物视频在线 | 九九在线免费视频 | 欧美巨大荫蒂茸毛毛人妖 | 中文字幕国内精品 | 少妇性xxx| 在线亚洲高清视频 | 99久久日韩精品视频免费在线观看 | 国产一区二区播放 | 欧美了一区在线观看 | 久久丁香网 | 久久久久免费观看 | 欧美日韩精品在线一区二区 | 国产黄色精品在线观看 | 久99久久| www.亚洲精品在线 | 西西人体4444www高清视频 | 国产福利一区二区三区视频 | 高清在线一区 | 国产综合精品一区二区三区 | 国产精品视频观看 | 久久在线精品视频 | 亚洲精品福利在线 | 日韩一区二区三区在线观看 | 96视频免费在线观看 | 欧美日韩一区二区三区在线观看视频 | 西西www4444大胆视频 | 精品极品在线 | 中文字幕国产视频 | 五月婷婷六月综合 | 国产精品女同一区二区三区久久夜 | 91精品视频观看 | 国产精品成人国产乱 | 日韩欧美有码在线 | 色老板在线视频 | 国产精品久久久久久模特 | 国产精品美女久久久久久免费 | 色黄视频免费观看 | 国产日本高清 | 伊人久久精品久久亚洲一区 | 韩日三级在线 | 91porny九色91啦中文 | 成人免费在线播放 | 99亚洲精品在线 | 久草在线免费看视频 | 免费观看的黄色片 | 国产成人精品午夜在线播放 | 久久69精品 | 日韩三级成人 | 国产剧情久久 | 国产麻豆果冻传媒在线观看 | 精品国产一区二区三区久久久久久 | 日本最新一区二区三区 | 99久久精品一区二区成人 | 激情视频网页 | 黄色网www| 国产精品自产拍在线观看中文 | 91久久精品日日躁夜夜躁国产 | 国产一级不卡视频 | 亚洲视频精品 | .国产精品成人自产拍在线观看6 | 日韩欧美高清在线 | 男女精品久久 | 亚洲精品乱码久久久一二三 | 天天看天天干 | 精品久久久久久亚洲 | 韩日av在线 | 色精品视频 | 综合网天天 | 久久天天躁狠狠躁夜夜不卡公司 | 一区二区三区视频网站 | 91精品久久久久久综合乱菊 | 国产一级性生活 | 亚洲日日夜夜 | 黄色小说视频在线 | 久久精品亚洲国产 | 国产91成人在在线播放 | 91亚洲精品乱码久久久久久蜜桃 | 国产精品久久久亚洲 | 日本一区二区免费在线观看 | 97看片吧 | 韩日av在线 | 中文字幕在线观看一区二区 | 亚洲免费av一区二区 | 9在线观看免费高清完整版在线观看明 | 久久久鲁 | 亚洲第五色综合网 | 韩国av一区二区三区在线观看 | 夜夜躁狠狠躁日日躁 | 日韩二区在线观看 | 中文字幕在线观看91 | 久久欧美在线电影 | 精品在线一区二区 | 国产视频美女 | 亚洲天堂网视频 | 亚洲午夜在线视频 | 婷婷精品在线视频 | 97超碰人人澡人人爱学生 | 91久久久久久国产精品 | 中文字幕在线播放一区二区 | 99久久网站| 91传媒激情理伦片 | 国产精品人成电影在线观看 | 欧美日韩国产一区二区在线观看 | 一级全黄毛片 | 最近日本韩国中文字幕 | 国产日韩在线一区 | 久久精品男人的天堂 | 中文字幕在线观看不卡 | 国产资源精品在线观看 | 日韩高清二区 | 亚州欧美精品 | 久久蜜臀av| 精品国产_亚洲人成在线 | 久久精品国产久精国产 | 欧美最猛性xxxxx亚洲精品 | 国产黄色免费 | wwxxxx日本 | 国产一区二区视频在线播放 | 国产伦精品一区二区三区四区视频 | 综合在线亚洲 | 五月婷婷在线播放 | a在线观看视频 | 色综合久久中文综合久久牛 | 亚洲人人射 | 在线观看日韩精品视频 | 成人国产精品久久久久久亚洲 | 日韩在线色 | 国产精品久99 | 亚洲美女视频网 | 欧美性春潮 | 亚洲国产三级在线观看 | 蜜桃麻豆www久久囤产精品 | 中文字幕在线视频网站 | 亚洲综合在线五月天 | 成年人电影免费看 | 麻豆极品| 97精品国产97久久久久久粉红 | 亚洲成a人片77777潘金莲 | 美女黄网站视频免费 | 网站在线观看你们懂的 | 国产免费一区二区三区网站免费 | 免费成人短视频 | 久久天天躁夜夜躁狠狠85麻豆 | 在线免费成人 | 一级片视频在线 | 国产成人精品日本亚洲999 | 五月激情亚洲 | 国内精品视频一区二区三区八戒 | 天天综合精品 | 偷拍精品一区二区三区 | 四虎影视成人永久免费观看亚洲欧美 | 91色一区二区三区 | 欧美精品一区二区免费 | 欧美最猛性xxxxx免费 | 久久免费电影 | 伊人天天狠天天添日日拍 | 亚洲视频h | 六月丁香激情综合 | 亚洲无吗视频在线 | 免费观看9x视频网站在线观看 | 成人久久18免费网站图片 | 久久久久免费精品国产 | 亚洲视频在线观看网站 | 国产高清av免费在线观看 | 亚洲综合最新在线 | 欧美一级免费在线 | 日韩伦理一区二区三区av在线 | 一个色综合网站 | 久久福利电影 | a天堂免费 | 久久综合加勒比 | 探花视频免费观看 | 色婷婷国产精品 | 欧美综合在线视频 | 亚洲精品免费在线视频 | 色网av| 精品视频99 | 国产精品亚 | av福利在线 | 99精品国产99久久久久久福利 | 日韩精品欧美视频 | 日韩免费一二三区 | 日韩精品一区二区在线观看 | 久久久久亚洲精品成人网小说 | 天天综合网久久综合网 | 69欧美视频| 国产中文字幕久久 | 亚洲免费av在线播放 | 日韩黄色在线 | 亚洲精选久久 | 国产综合视频在线观看 | 久久亚洲国产精品 | 极品久久久 | 久久久精品视频成人 | 九九免费在线观看 | 国产va饥渴难耐女保洁员在线观看 | 91色亚洲 | 狠狠色丁香婷婷综合久小说久 | 亚洲成av人片在线观看www | 国产色中涩 | 一区二区三区日韩视频在线观看 | 亚洲另类视频在线 | 91福利视频久久久久 | 91传媒免费观看 | www.com黄| 日韩欧美精品在线观看 | 国产999精品视频 | 亚洲欧美视频在线观看 | 在线观看av的网站 | 精品中文字幕视频 | 一本色道久久综合亚洲二区三区 | 中文字幕电影高清在线观看 | 在线免费观看不卡av | 一区二区视频免费在线观看 | 日韩美女免费线视频 | 日韩亚洲在线视频 | 999久久久久久| 亚洲综合爱 | 三级黄色片在线观看 | 欧美一级片播放 | 亚洲精品ww | 欧洲激情在线 | 婷婷午夜激情 | 日本资源中文字幕在线 | 九九热在线观看视频 | 9在线观看免费高清完整 | 成人黄色电影免费观看 | 狠狠色婷婷丁香六月 | 久久精彩免费视频 | 国产午夜影院 | 免费日韩 精品中文字幕视频在线 | 国产网红在线观看 | 日韩一区二区免费在线观看 | 日韩视频欧美视频 | 91爱爱电影 | 激情欧美一区二区三区 | 欧美一区中文字幕 | 午夜国产一区二区三区四区 | 国产成人精品一区二区三区福利 | 在线观看视频h | 丝袜美女视频网站 | 亚洲精品国产精品久久99热 | 亚洲区精品视频 | 国产女v资源在线观看 | 日韩欧美综合在线视频 | 黄色在线观看免费 | 色偷偷网站视频 | 91久色蝌蚪 | www.久久久.com | 久久午夜精品视频 | 91影视成人| 国产精品一区二区三区免费看 | 2021国产视频 | 国产精品成久久久久三级 | 日韩手机在线观看 | 丁香花五月| 免费碰碰 | 久久久激情视频 | a视频在线观看免费 | 91精品一区二区三区久久久久久 | 夜夜操夜夜干 | 日日干美女| 国产区免费| 日韩三区在线 | 国产精品女同一区二区三区久久夜 | 久久精品屋| 亚洲免费黄色 | 又色又爽又激情的59视频 | 在线国产小视频 | 亚洲久草网 | 亚洲成色777777在线观看影院 | 啪啪小视频网站 | 亚洲h在线播放在线观看h | 成人综合婷婷国产精品久久免费 | 欧美国产一区二区 | 午夜精品电影 | 国产人免费人成免费视频 | 色中色综合| 久久理论影院 | 精品999国产| 在线观看免费av网站 | 国产一级免费观看 | 免费av影视 | 免费视频一区二区 | 欧美日韩国产在线观看 | www免费视频com━ | 久久黄色免费观看 | 久草在线视频首页 | 成片视频在线观看 | 黄色毛片视频免费观看中文 | 亚洲精品在线观看av | 91精品久久久久久 | 国产在线观看午夜 | 成年人视频在线 | 午夜美女福利直播 | 国产韩国日本高清视频 | 久久国产精品久久国产精品 | 狠狠色噜噜狠狠 | 亚洲影院天堂 | 国产成人三级在线 | 操天天操| 欧美激情视频一区二区三区免费 | 久久久久久久福利 | 亚洲国产精品999 | 深爱婷婷 | 在线欧美最极品的av | 在线观看完整版免费 | 欧美黑人性猛交 | 四虎在线影视 | 成人黄色毛片视频 | 永久中文字幕 | 在线观看免费版高清版 | av高清在线 | 国产一级片直播 | 黄色网址中文字幕 | 久久久久区 | 麻豆传媒电影在线观看 | 国产无区一区二区三麻豆 | www.eeuss影院av撸 | 91成人在线观看高潮 | 91av在线免费 | 久久精品国产99国产 | 久久久免费观看完整版 | 国色天香在线 | 狠狠干夜夜操天天爽 | 免费一级黄色 | 99国产精品久久久久老师 | 亚洲精品97 | 国产一级视频在线 | 中文字幕免费高清在线 | 国产高清在线永久 | 国产成人在线网站 | 日韩在线免费高清视频 | 亚洲观看黄色网 | 深夜精品福利 | 五月丁色 | 精品在线免费观看 | 久久久亚洲精华液 | 成人福利在线播放 | 国产精品成人av电影 | 91污视频在线观看 | 日韩国产精品一区 | 国产精品久久久久毛片大屁完整版 | 一区二区三区四区五区六区 | 亚色视频在线观看 | 日韩久久久久久久久 | 午夜精品在线看 | 黄色免费观看视频 | 色噜噜狠狠狠狠色综合 | 色婷久久| av千婊在线免费观看 | 久久精品在线免费观看 | 正在播放一区 | 国产福利久久 | 日韩高清av | 麻豆久久久 | 99国产成+人+综合+亚洲 欧美 | 二区三区在线观看 | 成年人网站免费观看 | www久久| 九九免费在线看完整版 | 麻豆传媒视频在线播放 | 国产女人40精品一区毛片视频 | 又污又黄的网站 | 欧美男同视频网站 | 久久久精选 | 91麻豆免费版 | 人人狠狠综合久久亚洲婷 | 国产专区第一页 | 日日干 天天干 | 四虎成人免费影院 | 久久久久久高潮国产精品视 | 国产精品高潮久久av | 国产一区二区三精品久久久无广告 | 久久观看免费视频 | 精品福利视频在线 | 一个色综合网站 | 精品久久久亚洲 | 国产精品热 | 丁香五月亚洲综合在线 | 91成人免费在线视频 | 免费黄色小网站 | 午夜精品久久久久久久久久久久久久 | 久久久影视| 国产精品色婷婷 | 亚洲精品综合一二三区在线观看 | 91精品久久久久久综合乱菊 | 成人观看 | 国产网红在线 | 胖bbbb搡bbbb擦bbbb | 国内精品久久久久久久影视麻豆 | 色噜噜在线观看 | 黄色片网站大全 | 国产精品高清免费在线观看 | 天天玩天天操天天射 | 国产网站在线免费观看 | 欧美成亚洲 | 亚洲一区二区天堂 | 99r精品视频在线观看 | 国产日韩视频在线播放 | 99热这里只有精品在线观看 | 中文在线a∨在线 | 亚洲国产天堂av | 日批网站免费观看 | 国产手机视频在线播放 | 日本少妇久久久 | 中文字幕a∨在线乱码免费看 | 色综合久久88色综合天天 | 麻豆果冻剧传媒在线播放 | 2019中文最近的2019中文在线 | 亚洲经典视频 | 免费久久久 | 五月天色综合 | 欧美日韩免费观看一区二区三区 | 免费三级影片 | 亚洲毛片久久 | 国产亚洲人成网站在线观看 | 国产精品初高中精品久久 | 欧美午夜理伦三级在线观看 | 久草在线资源免费 | 国产成人精品一区在线 | 午夜在线观看一区 | 色播五月激情五月 | 欧美一级爽 | 伊人五月天| 久久艹精品 | 国产高清免费av | 亚洲国产综合在线 | 欧美一级免费片 | 亚洲国产日韩av | 久久久久久久久影院 | 久久国产一区 | 中文字幕亚洲精品日韩 | 欧美性色黄大片在线观看 | 人人爽人人爽人人 | 精品在线视频一区二区三区 | 中文字幕在线网址 | 色姑娘综合网 | 96av视频| 免费观看91视频大全 | 国产精品电影一区二区 | 亚洲精品国产精品乱码不99热 | 美女黄频在线观看 | 91av片| 国产成人av电影在线观看 | 西西www4444大胆视频 | 天天艹天天 | 国产在线观看你懂的 | www.天天干| 欧美日韩在线观看一区 | 伊人手机在线 | 精品国产一区二区久久 | 国产精品久久久久久久久毛片 | 美女av电影| 碰超在线97人人 | 日日夜夜网 | 九色在线视频 | 黄色aaa毛片| 亚洲清纯国产 | 亚洲无在线| 欧美精品成人在线 | 国产小视频网站 | 国产精品一区欧美 | 日韩av片无码一区二区不卡电影 | 免费在线观看a v | 夜夜干天天操 | 久久人人爽人人爽 | 免费观看国产视频 | 亚洲成人蜜桃 | 国产精品嫩草影视久久久 | 国产精品久久久久久一区二区三区 | 久久综合久久综合九色 | av五月婷婷 | 在线免费av观看 | 中文av日韩 | www.色国产 | 色午夜影院| www.午夜色.com | 97超碰精品 | 日本中文字幕免费观看 | 玖玖视频精品 | 麻豆一区二区三区视频 | 国产高清一区二区 | 国产精品正在播放 | 日韩欧美国产视频 | 黄色一级免费电影 | 日本三级人妇 | a级国产乱理论片在线观看 特级毛片在线观看 | 五月天狠狠操 | 成人av资源网 | 久久永久免费视频 | 亚洲欧美视频在线播放 | 国产亚洲久一区二区 | 成人啊 v| 激情综合网五月婷婷 | 日韩资源在线观看 | www.狠狠 | 久久久资源网 | 成人免费xxx在线观看 | 天天色天天操天天爽 | 国产美女精品在线 | 色网站在线看 | 久久99国产精品自在自在app | 在线视频电影 | 四虎成人精品永久免费av | av解说在线 | 成人av电影免费在线播放 | 欧美成人h版 | 一区二区中文字幕在线播放 | 999电影免费在线观看 | 天天干,天天操 | 夜夜躁狠狠躁 | 国产中文字幕在线观看 | 在线视频 精品 | 99婷婷狠狠成为人免费视频 | 亚洲伊人天堂 | 久久激情视频网 | 在线观看成人网 | 国产日韩精品久久 | 1000部国产精品成人观看 | 免费看高清毛片 | 九色porny真实丨国产18 | av天天在线观看 | 亚洲va欧美va国产va黑人 | 91精选在线观看 | 香蕉在线视频观看 | 欧美91视频| 欧美日韩精品免费观看 | 久久国产精品二国产精品中国洋人 | 人人爽人人爽人人爽人人爽 | 亚洲日韩精品欧美一区二区 | 天天干天天做 | 中文字幕刺激在线 | 日韩理论电影网 | 操少妇视频 | 91精品国自产在线 | 国产精在线 | 国偷自产中文字幕亚洲手机在线 | 欧美精品一区二区三区一线天视频 | 午夜精品久久久久久久99水蜜桃 | 在线观看一区二区精品 | 精品国产一区二区三区久久久蜜月 | 狠狠干夜夜爱 | 精品一二三四视频 | 日韩在线视频精品 | 午夜久久美女 | 91精品久久久久久综合乱菊 | 九九久久免费视频 | 久久久久久久18 | 人人爽人人做 | 9797在线看片亚洲精品 | 操处女逼 | 色综合久久综合网 | h视频在线看 | 一区二区三区污 | 免费观看版 | 欧美成人区 | 久久久久久国产精品亚洲78 | www.夜夜夜| 成人黄色电影在线播放 | 欧美专区国产专区 | 国产美女精品人人做人人爽 | 国产免费影院 | 在线观看av国产 | 欧美另类人妖 | 91久久精品一区 | 久久草av | 午夜av免费在线观看 | 五月天婷婷在线观看视频 | 免费国产在线精品 | 六月色| 成年人视频在线免费 | 国产性天天综合网 | 国产伦理精品一区二区 | 国内一区二区视频 | 女人高潮一级片 | 色在线最新| 一区二区三区视频 | 主播av在线 | 91精品中文字幕 | 97色噜噜 | 亚洲自拍偷拍色图 | 国产精品久久久久久久久久久杏吧 | 久草精品免费 | 亚洲综合在线一区二区三区 | 伊人日日干 | 激情综合啪啪 | 99久免费精品视频在线观看 | 欧美日韩二区在线 | 激情综合电影网 | 韩国一区二区三区视频 | 91人网站 | 国产精品二区三区 | 美女免费黄视频网站 | 一级免费看视频 | 五月天亚洲婷婷 | 日韩免费电影网 | 欧美日韩国产区 | 美女免费视频一区 | 精品国产自在精品国产精野外直播 | 国产高清在线a视频大全 | 欧美成人精品欧美一级乱黄 | 久久综合九色综合欧美狠狠 | 久久国产精品99精国产 | 超碰999 | 亚洲视频在线观看 | 在线观看91视频 | 国产第一二区 | 国产高清视频 | 91看片淫黄大片91 | a在线视频v视频 | 国产91在线 | 美洲 | 久久电影中文字幕视频 | 日韩精品欧美视频 | 欧美特一级片 | 免费在线激情视频 | 成人资源站| 九九热视频在线免费观看 | 成 人 黄 色 视频 免费观看 | 国产手机免费视频 | av在线不卡观看 | 婷婷五综合 | 日三级在线 | 日韩中文字幕亚洲一区二区va在线 | 国产福利在线 | 欧美一区二区在线免费看 | 久久精品国产免费看久久精品 | 亚洲动漫在线观看 | av久久久 | 人人看人人做人人澡 | 精品久久久一区二区 | 色婷婷亚洲精品 | 国内精品久久久久久久97牛牛 | 久久黄色影视 | 中文字幕日韩国产 | 国产精品一区二区三区免费看 | 亚洲欧美日韩一级 | 在线国产黄色 | 国产精品久久久久久久久久东京 | 日韩久久精品一区二区 | 九色最新网址 | 久久不卡av | 波多野结衣电影一区二区三区 | 欧美成人理伦片 | 亚洲激情小视频 | 日韩精品视频免费在线观看 | 国产精品久久99精品毛片三a | 欧美日韩中字 | 欧美一区在线观看视频 | 99视频这里有精品 | 国产a高清| 婷婷在线观看视频 | 国内外成人在线 | 久久在线视频在线 | 久久久久久久久久网站 | 97人人爽人人 | 九色最新网址 | 狠狠色狠狠色综合日日小说 | 日韩一区二区免费在线观看 | 日韩在线精品视频 | 成人精品国产免费网站 | 久久热亚洲 | 又黄又爽又色无遮挡免费 | 亚洲黄色在线观看 | 国产乱码精品一区二区蜜臀 | 在线中文字幕视频 | 99久久日韩精品视频免费在线观看 | 综合影视 | 黄污网站在线观看 | 美女精品在线 | 国内丰满少妇猛烈精品播 | 91在线蜜桃臀 | av在线激情 | 久久久久99精品成人片三人毛片 | 中文字幕 影院 | 国产精品久久久久久久久搜平片 | 国产精品久久久久久久久免费看 | 欧美伊人网| 91网在线看 | 免费看的黄色片 | 91精品久久香蕉国产线看观看 | 日韩成人高清在线 | 女人高潮特级毛片 | 欧美 激情在线 | 五月婷婷色丁香 | 中文在线中文资源 | 少妇性bbb搡bbb爽爽爽欧美 | 国产精品手机在线播放 | 999超碰| 国产91精品欧美 | a在线播放 | 久久精品99北条麻妃 | 91秒拍国产福利一区 | 亚洲综合五月天 | 欧美一级激情 | 丁香六月在线 | 精品一区二区在线播放 | 日韩精品欧美视频 | 免费成人在线视频网站 | 亚洲91av| 成年人国产在线观看 | 久久资源在线 | 亚洲天堂在线观看完整版 | 久久精品—区二区三区 | 岛国大片免费视频 | 国产精品11 | 玖玖视频在线 | 久久久久久久国产精品视频 | 三级av网站 | 91av片 | 激情视频免费在线观看 | 麻豆av一区二区三区在线观看 | 91毛片在线| 男女免费视频观看 | 久久99免费 | av丝袜制服 | 亚洲国产成人久久综合 | 麻豆国产露脸在线观看 | 国产91精品久久久久 | 欧美日韩亚洲第一页 | 久久激情综合 | 在线欧美中文字幕 | 亚洲最新在线视频 | 欧美精品久久久久久久久久白贞 | 四虎影视4hu4虎成人 | 麻豆久久久久 | 日韩有码欧美 | 伊人久久在线观看 | 日韩理论电影在线观看 | 久久99久久99精品免观看粉嫩 | 国产成人精品免高潮在线观看 | 久久99久久久久久 | 免费高清在线视频一区· | 视频在线一区 | 亚洲欧美一区二区三区孕妇写真 | 久久香蕉一区 | 成人黄色资源 | 色偷偷网站视频 | 欧美精品一区在线 | 久久资源在线 | 在线观看免费福利 | 99久久99久久精品国产片 | 国产日韩精品一区二区三区在线 | 人人插人人搞 | 波多野结衣在线中文字幕 | 亚洲国产成人久久 | 欧美性极品xxxx娇小 | 国产精品手机播放 | 久久免费电影 | 国产色视频一区二区三区qq号 | 午夜精品一区二区三区可下载 | 狠狠干美女 | 毛片黄色一级 | 黄色小说视频网站 | 亚洲精品影视 | 日韩欧美国产激情在线播放 | av电影中文字幕 | 免费看片网址 | 亚洲资源视频 | 美女久久久久久久久久久 | 久久99国产精品久久 | 五月婷香 | 国产午夜精品av一区二区 | 国产黄在线免费观看 | 亚洲成人黄色网址 | 娇妻呻吟一区二区三区 | 天天爱av导航 | www.伊人网 | av网站有哪些 | 91精品视频导航 | 国产尤物在线视频 | 国产精品刺激对白麻豆99 | 在线视频电影 | 婷婷网址 | 久久综合九色九九 |