UWB是一種無線載波通信技術,利用納秒級的非正弦波窄脈沖傳輸數據,工作頻段在3.25GHZ~6.75GHZ,頻寬典型值為500MHZ或者1GHZ,所以可以獲取亞納米的精確時間(1ns約等於750px)。UWB也可用於傳輸數據,普通幀大約在128字節,擴展幀則能傳輸K級別的數據。
與普通的通信不同,UWB直接使用數字波形來傳輸數據,而一般的無線通信使用了載波。
通過二者通信的時間戳,我們能利用TOF的方法,來獲得兩個模塊之間的距離。這個算法就是測距算法。
1. 單邊算法:
我們有兩個模塊,Device A ,DeviceB,他們按照如下流程工作:
- deviceA 首先發送一個帶時間戳的幀至 deviceB
- deviceB收到幀的同時開始啟動定時T_replay。
- DeviceB 發送回應幀,並把定時間隔T_replay附加在幀中。
- DeviceA 收到回應幀的同時,計算出發送接收間隔T_round ,並從幀中得到T_replay。
這樣,DeviceA 就得到了計算需要的關鍵數據:T_round ,T_replay。
而通過計算,就能得到微波在空間中的傳輸時間T_prop
由於微波是以光速C運行的,進而通過C*T_prop得到傳輸距離,完成測距。
T_prop算法如下:
T_prop = (Tround - T_replay) /2
T_prop的誤差:
由於模塊自身的時鍾是有誤差的,所以時間采集也有誤差。我們假定,DeviceA的時鍾誤差為e_a, DeviceB的時鍾誤差為e_b.
按照資料上看,誤差計算公式是:
Error≈ 1/2 * (e_b-e_a) / T_replay
按照我自己的計算,誤差應該是:
Error = ( e_a*Troud*(1+e_b) – e_b*T_replay*(1+e_a) ) / (Tround(1+e_b) -T_replay*(1+e_a))
現在還不明白這個誤差公式是怎么推導出來的。
二. 雙邊算法:
這里用最常用的三次消息法來說明:
計算距離時,公式如下圖:
T_prop = (T_ound1*T_ound2 – Treplay1*Treplay2) / ( Tround1 + Tound2 +Treplay1 + Treplay2)
我不嚴謹的分析了下,當T1,T2是一個確定的時間,誤差出現在時間讀數上時:
T_round1 * T_round2 = T1^2 * e_a*e_b
Treplay1 * Treplay2 = T2^2 * e_a*e_b
資料上,其誤差公式如下:
Error = T_prop *(1- (ka+kb)/2)
其中,ka, kb 時設備A,設備B的運行頻率,接近於1.具體什么含義我也不清楚。
由於確實買看懂誤差公式,所以我使用python來暴力列舉了下,在當設備誤差在(+-0.01),也就是百分之1之內,使用不同的算法,誤差有多大。
這里涉及到兩個設備,我讓E_a,E_b互相獨立,設定Tround=2400,Treplay = 1800,計算其誤差。
得到如下對比的誤差圖。,其中X軸是e_a誤差, Y軸是e_b誤差。Z軸是在設備處於e_a,e_b誤差下,測距算法的誤差百分比。
可見,使用DTR(雙邊雙向) 算法,誤差保存在+-1%之間, 而使用STR(單邊)算法,誤差在+-6%之間。
最后時代碼:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D ax = plt.figure().add_subplot(111, projection = '3d') bx = plt.figure().add_subplot(111, projection = '3d') #單邊算法 求各E_a ,E_b 下的測距誤差,輸入為真實時間 def STR_E(T_round=2400,T_replay=1800): for x in range(990,1010): for y in range(990,1010): x_f = x/1000 y_f = y /1000 z_r = (T_round - T_replay)/2 z_e = (T_round*x_f - T_replay*y_f)/2 error = (z_e - z_r)/z_r *100 point = [x_f,y_f,error]; yield point #雙邊算法 求各E_a ,E_b 下的測距誤差 ,輸入為真實時間 def DTR_E(T_round=2400,T_replay=1800): for x in range(990,1010): for y in range(990,1010): x_f = x/1000 y_f = y/1000 T1_e = T_round*x_f T2_e = T_replay*y_f T3_e = T_round*y_f T4_e = T_replay*x_f muti = T1_e*T3_e-T2_e*T4_e summ = T1_e+T2_e+T3_e+T4_e z_e = muti / summ z_r = (T_round - T_replay)/2 error = (z_e - z_r)/z_r *100 point = [x_f,y_f,error]; yield point #使用生成器,速度很慢 #for pp in DTR_E(): #ax.scatter(pp[0],pp[1],pp[2], c = 'r', marker = '.') #點為紅色三角形 #先把數據寫入列表,然后再顯示,速度快 px=[] py=[] pz=[] for point in DTR_E(): px.append(point[0]) py.append(point[1]) pz.append(point[2]) ax.scatter(px,py,pz, c = 'r', marker = '.') #點為紅色三角形 pbx=[] pby=[] pbz=[] for point in STR_E(): pbx.append(point[0]) pby.append(point[1]) pbz.append(point[2]) bx.scatter(pbx,pby,pbz, c = 'r', marker = '.') #點為紅色三角形 #設置坐標軸 ax.set_xlabel('X Label') ax.set_ylabel('Y Label') ax.set_zlabel('Z Label') bx.set_xlabel('X Label') bx.set_ylabel('Y Label') bx.set_zlabel('Z Label') #顯示圖像 plt.show()