DOP
Dillution of Precision (DOP) describes the effect of satellite geometry on the user’s positioning accuracy. DOP can refer to multiple ideas:
DOP in the horizontal or vertical direction,
DOP on the time uncertainty,
The full DOP matrix, or
DOP in a particular direction.
Here we show how to make use of existing functionality. For more details on the underlying math, please see the Navipedia page on positioning error.
[1]:
import gnss_lib_py as glp
import numpy as np
# A library for url downloads that works regardless of `wget` command
import urllib.request
As an example, we can load in data from the 2022 Google Smartphone Decimeter Challenge
[2]:
glp.make_dir("../data")
urllib.request.urlretrieve("https://raw.githubusercontent.com/Stanford-NavLab/gnss_lib_py/main/data/unit_test/google_decimeter_2022/device_gnss.csv", "../data/device_gnss.csv")
navdata = glp.AndroidDerived2022("../data/device_gnss.csv")
Since we already have elevation and azimuth data available to us, we can simply call the get_dop
function, which will only return the HDOP and VDOP values, by default. HDOP corresponds to the dilution of precision in the horizontal direction (i.e., East and North plane), and VDOP corresponds to the dilution of precision in the vertical direction (i.e., the Up axis).
[3]:
dop_navdata = glp.get_dop(navdata)
print(dop_navdata)
gps_millis HDOP VDOP
0 1.303771e+12 0.558578 0.830517
1 1.303771e+12 0.549160 0.829362
2 1.303771e+12 0.558593 0.830452
3 1.303771e+12 0.549176 0.829296
4 1.303771e+12 0.549185 0.829263
5 1.303771e+12 0.549193 0.829230
Some applications may care about the dilution of precision in time (TDOP), but may not be interested in the dilution of precision in position. Simply pass this information to the parser.
[4]:
dop_navdata = glp.get_dop(navdata, HDOP=False, VDOP=False, TDOP=True)
print(dop_navdata)
gps_millis TDOP
0 1.303771e+12 0.533824
1 1.303771e+12 0.529356
2 1.303771e+12 0.533763
3 1.303771e+12 0.529294
4 1.303771e+12 0.529263
5 1.303771e+12 0.529233
Below we illustrate all supported DOP types. The full DOP matrix (in ENU) is
The matrix is symmetric (i.e., \(q_{en} = q_{ne}\)). Often the elements along the diagonal are of primary interest
To store the dop matrix \(Q\) in dop_navdata
, the upper triangle is splatted across columns to enable fast storage and access in the navdata using numpy.
[5]:
dop_navdata = glp.get_dop(navdata, GDOP= True, HDOP=True, VDOP=True,
PDOP=True, TDOP=True, dop_matrix=True)
print(dop_navdata)
gps_millis GDOP HDOP VDOP PDOP TDOP dop_ee \
0 1.303771e+12 1.134343 0.558578 0.830517 1.000883 0.533824 0.163043
1 1.303771e+12 1.126781 0.549160 0.829362 0.994695 0.529356 0.157412
2 1.303771e+12 1.134275 0.558593 0.830452 1.000838 0.533763 0.163059
3 1.303771e+12 1.126711 0.549176 0.829296 0.994649 0.529294 0.157430
4 1.303771e+12 1.126677 0.549185 0.829263 0.994626 0.529263 0.157439
5 1.303771e+12 1.126642 0.549193 0.829230 0.994603 0.529233 0.157448
dop_en dop_eu dop_et dop_nn dop_nu dop_nt dop_uu \
0 -0.033487 0.071130 -0.034933 0.148966 -0.107539 0.065920 0.689758
1 -0.038702 0.074427 -0.040130 0.144165 -0.104554 0.061164 0.687841
2 -0.033509 0.071241 -0.035010 0.148967 -0.107550 0.065927 0.689650
3 -0.038724 0.074539 -0.040206 0.144165 -0.104563 0.061170 0.687732
4 -0.038735 0.074596 -0.040245 0.144165 -0.104567 0.061173 0.687677
5 -0.038745 0.074652 -0.040284 0.144165 -0.104572 0.061177 0.687623
dop_ut dop_tt
0 -0.410704 0.284968
1 -0.407697 0.280218
2 -0.410618 0.284903
3 -0.407610 0.280152
4 -0.407566 0.280120
5 -0.407523 0.280087
We can recover the unsplatted versions of the DOP matrix as needed if we loop through time.
[6]:
for timestamp, _, dop_navdata_subset in glp.loop_time(dop_navdata, 'gps_millis'):
labels = glp.get_enu_dop_labels()
dop_matrix_splat = np.array(
[dop_navdata_subset[f'dop_{label}'] for label in labels])
print(f"At time {timestamp} the DOP matrix is")
print(glp.unsplat_dop_matrix(dop_matrix_splat))
At time 1303770943999.0 the DOP matrix is
[[ 0.16304289 -0.03348691 0.07112954 -0.03493291]
[-0.03348691 0.14896632 -0.10753946 0.0659197 ]
[ 0.07112954 -0.10753946 0.68975786 -0.4107043 ]
[-0.03493291 0.0659197 -0.4107043 0.28496798]]
At time 1303770944999.0 the DOP matrix is
[[ 0.15741177 -0.03870195 0.07442678 -0.04012966]
[-0.03870195 0.14416461 -0.10455384 0.06116369]
[ 0.07442678 -0.10455384 0.68784096 -0.40769683]
[-0.04012966 0.06116369 -0.40769683 0.28021779]]
At time 1303770945999.0 the DOP matrix is
[[ 0.16305935 -0.03350896 0.07124139 -0.03501028]
[-0.03350896 0.14896727 -0.10754991 0.06592695]
[ 0.07124139 -0.10754991 0.68964999 -0.41061842]
[-0.03501028 0.06592695 -0.41061842 0.28490285]]
At time 1303770946999.0 the DOP matrix is
[[ 0.15742999 -0.03872364 0.07453933 -0.04020645]
[-0.03872364 0.14416459 -0.10456265 0.0611701 ]
[ 0.07453933 -0.10456265 0.68773184 -0.40760979]
[-0.04020645 0.0611701 -0.40760979 0.28015229]]
At time 1303770947999.0 the DOP matrix is
[[ 0.15743916 -0.03873452 0.07459567 -0.0402449 ]
[-0.03873452 0.14416463 -0.10456715 0.06117339]
[ 0.07459567 -0.10456715 0.68767735 -0.4075664 ]
[-0.0402449 0.06117339 -0.4075664 0.28011966]]
At time 1303770948999.0 the DOP matrix is
[[ 0.15744842 -0.03874549 0.07465221 -0.04028354]
[-0.03874549 0.14416482 -0.10457202 0.061177 ]
[ 0.07465221 -0.10457202 0.68762276 -0.40752307]
[-0.04028354 0.061177 -0.40752307 0.28008714]]
Lastly, we can compute the contribution in a particular direction with numpy.
[7]:
direction_of_interest = np.array([-1, 1, 0, 0])
# Normalize the direction of interest
direction_of_interest = direction_of_interest / np.linalg.norm(direction_of_interest)
for timestamp, _, dop_navdata_subset in glp.loop_time(dop_navdata, 'gps_millis'):
labels = glp.get_enu_dop_labels()
dop_matrix_splat = np.array(
[dop_navdata_subset[f'dop_{label}'] for label in labels])
dop_matrix_unsplat = glp.unsplat_dop_matrix(dop_matrix_splat)
dop_in_direction = np.sqrt(
direction_of_interest @ dop_matrix_unsplat @ direction_of_interest)
print(f"At time {timestamp} the DOP in the direction of interest is {dop_in_direction}")
At time 1303770943999.0 the DOP in the direction of interest is 0.43530623907154725
At time 1303770944999.0 the DOP in the direction of interest is 0.43530464856176754
At time 1303770945999.0 the DOP in the direction of interest is 0.43534155075325415
At time 1303770946999.0 the DOP in the direction of interest is 0.43534001360708996
At time 1303770947999.0 the DOP in the direction of interest is 0.4353578004877099
At time 1303770948999.0 the DOP in the direction of interest is 0.43537583394008916