99
1010from gnss_lib_py .navdata .navdata import NavData
1111from gnss_lib_py .navdata .operations import loop_time
12+ from gnss_lib_py .utils .coordinates import el_az_to_enu_unit_vector
1213
1314
1415def get_dop (navdata , ** which_dop ):
@@ -114,60 +115,70 @@ def get_dop(navdata, **which_dop):
114115 return dop_navdata
115116
116117
117- def calculate_dop (derived ):
118- """Calculate DOP from elevation and azimuth (ENU).
119118
119+ def calculate_enu_dop_matrix (derived ):
120+ """
121+ Calculate the DOP matrix from elevation and azimuth (ENU).
122+
120123 Parameters
121124 ----------
122125 derived : gnss_lib_py.navdata.navdata.NavData
123126 NavData instance containing received GNSS measurements for a
124127 particular time instance, contains elevation and azimuth angle
125128 information for an estimated location.
126-
129+
127130 Returns
128131 -------
129- dop : Dict
130- Dilution of precision, with DOP type as the keys: "HDOP", "VDOP",
131- "TDOP", "PDOP", "GDOP".
132+ dop_matrix : np.ndarray (4, 4)
133+ DOP matrix.
132134 """
133135
134136 # Use the elevation and azimuth angles to get the ENU and Time matrix
135137 # Each row is [d_e, d_n, d_u, 1] for each satellite.
136138 enut_matrix = _calculate_enut_matrix (derived )
137139 enut_gram_matrix = enut_matrix .T @ enut_matrix
138-
139- try :
140- dop_matrix = np .linalg .inv (enut_gram_matrix )
141-
142- # Calculate the DOP
143- dop = {}
144- dop ["dop_matrix" ] = dop_matrix
145- dop ["GDOP" ] = np .sqrt (np .trace (dop_matrix ))
146- dop ["HDOP" ] = np .sqrt (dop_matrix [0 , 0 ] + dop_matrix [1 , 1 ])
147- dop ["VDOP" ] = np .sqrt (dop_matrix [2 , 2 ])
148- dop ["PDOP" ] = np .sqrt (dop_matrix [0 , 0 ] + \
149- dop_matrix [1 , 1 ] + \
150- dop_matrix [2 , 2 ])
151- dop ["TDOP" ] = np .sqrt (dop_matrix [3 , 3 ])
152140
141+ # Calculate the DOP matrix
142+ try :
143+ dop_matrix = np .linalg .inv (enut_gram_matrix )
153144 except np .linalg .LinAlgError :
154145 # If the matrix is singular, return NaNs for the DOP
155- dop = {}
156- dop ["dop_matrix" ] = np .nan * np .ones ((4 , 4 ))
157- dop ["GDOP" ] = np .nan
158- dop ["HDOP" ] = np .nan
159- dop ["VDOP" ] = np .nan
160- dop ["PDOP" ] = np .nan
161- dop ["TDOP" ] = np .nan
146+ dop_matrix = np .nan * np .ones ((4 , 4 ))
147+
148+ return dop_matrix
149+
150+
151+ def parse_dop (dop_matrix ):
152+ """Calculate DOP types from the DOP matrix.
153+
154+ Parameters
155+ ----------
156+ dop_matrix : np.ndarray (4, 4)
157+ DOP matrix in ENU coordinates.
158+
159+ Returns
160+ -------
161+ dop : Dict
162+ Dilution of precision, with DOP type as the keys: "HDOP", "VDOP",
163+ "TDOP", "PDOP", "GDOP".
164+ """
165+
166+ dop = {}
167+ dop ["dop_matrix" ] = dop_matrix
168+ dop ["GDOP" ] = np .sqrt (np .trace (dop_matrix ))
169+ dop ["HDOP" ] = np .sqrt (dop_matrix [0 , 0 ] + dop_matrix [1 , 1 ])
170+ dop ["VDOP" ] = np .sqrt (dop_matrix [2 , 2 ])
171+ dop ["PDOP" ] = np .sqrt (dop_matrix [0 , 0 ] + \
172+ dop_matrix [1 , 1 ] + \
173+ dop_matrix [2 , 2 ])
174+ dop ["TDOP" ] = np .sqrt (dop_matrix [3 , 3 ])
162175
163176 return dop
164177
165178
166- def calculate_enu_unit_vectors (derived ):
179+ def calculate_dop (derived ):
167180 """
168- Calculate the ENU unit vectors from elevation and azimuth.
169- Each row is [d_e, d_n, d_u] for each satellite, where d is a unit
170- line-of-sight vector in the ENU frame.
181+ Calculate the DOP from elevation and azimuth (ENU).
171182
172183 Parameters
173184 ----------
@@ -178,21 +189,18 @@ def calculate_enu_unit_vectors(derived):
178189
179190 Returns
180191 -------
181- unit_dir_mat : np.ndarray (num_satellites, 3)
182- Matrix of ENU unit vectors.
192+ dop : Dict
193+ Dilution of precision, with DOP type as the keys: "HDOP", "VDOP",
194+ "TDOP", "PDOP", "GDOP".
183195 """
184196
185- # Get the elevation and azimuth angles
186- sv_el_az_rad = np . deg2rad (derived [ 'el_sv_deg' , 'az_sv_deg' ] )
197+ # Calculate the DOP matrix
198+ dop_matrix = calculate_enu_dop_matrix (derived )
187199
188- # Important: This matrix is in ENU coordinates, not NED.
189- unit_dir_mat = np .vstack (
190- (np .atleast_2d (np .cos (sv_el_az_rad [0 ,:]) * np .sin (sv_el_az_rad [1 ,:])),
191- np .atleast_2d (np .cos (sv_el_az_rad [0 ,:]) * np .cos (sv_el_az_rad [1 ,:])),
192- np .atleast_2d (np .sin (sv_el_az_rad [0 ,:]))
193- )).T
200+ # Parse the DOP matrix to get the DOP values
201+ dop = parse_dop (dop_matrix )
194202
195- return unit_dir_mat
203+ return dop
196204
197205
198206def _calculate_enut_matrix (derived ):
@@ -213,8 +221,9 @@ def _calculate_enut_matrix(derived):
213221 Matrix of ENU and Time vectors.
214222
215223 """
216- unit_dir_mat = calculate_enu_unit_vectors (derived )
217- enut_matrix = np .hstack ((unit_dir_mat ,
218- np .ones ((unit_dir_mat .shape [0 ], 1 ))))
224+ enu_unit_dir_mat = el_az_to_enu_unit_vector (derived ['el_sv_deg' ],
225+ derived ['az_sv_deg' ])
226+ enut_matrix = np .hstack ((enu_unit_dir_mat ,
227+ np .ones ((enu_unit_dir_mat .shape [0 ], 1 ))))
219228
220229 return enut_matrix
0 commit comments