@@ -47,7 +47,6 @@ def __init__(self, input_paths):
4747 input_paths = [input_paths ]
4848
4949 gps_millis = []
50- unix_millis = []
5150 gnss_sv_ids = []
5251 gnss_id = []
5352 sv_id = []
@@ -104,94 +103,78 @@ def __init__(self, input_paths):
104103 self ["y_sv_m" ] = y_sv_m
105104 self ["z_sv_m" ] = z_sv_m
106105
107- def extract_sp3 (self , gnss_sv_id , sidx , ipos = 10 , \
108- method = 'CubicSpline' , verbose = False ):
109- """Computing interpolated function over sp3 data for any GNSS
106+ def interpolate_sp3 (self , navdata , window = 6 , verbose = False ):
107+ """Interpolate ECEF position data from sp3 file, inplace to
108+ given navdata instance.
110109
111110 Parameters
112111 ----------
113- gnss_sv_id : string
114- PRN of satellite for which position should be determined.
115- sidx : int
116- Nearest index within sp3 time series around which interpolated
117- function needs to be centered.
118- ipos : int
119- No. of data points from sp3 data on either side of sidx
120- that will be used for computing interpolated function.
121- method : string
122- Type of interpolation method used for sp3 data (the default is
123- CubicSpline, which depicts third-order polynomial).
112+ navdata : gnss_lib_py.parsers.navdata.NavData
113+ Instance of the NavData class that must include rows for
114+ ``gps_millis`` and ``gnss_sv_id``.
115+ window : int
116+ Number of points to use in interpolation window.
124117 verbose : bool
125- If true, prints extra debugging statements.
118+ Flag (True/False) for whether to print intermediate steps useful
119+ for debugging/reviewing (the default is False)
126120
127- Returns
128- -------
129- func_satpos : np.ndarray
130- Instance with 3-D array of scipy.interpolate.interpolate.interp1d
131- that is loaded with .sp3 data
132121 """
122+ # add satellite indexes if not present already.
123+ sv_idx_keys = ['x_sv_m' , 'y_sv_m' , 'z_sv_m' , \
124+ 'vx_sv_mps' ,'vy_sv_mps' ,'vz_sv_mps' ]
133125
134- sp3data = self .where ("gnss_sv_id" ,gnss_sv_id )
126+ for sv_idx_key in sv_idx_keys :
127+ if sv_idx_key not in navdata .rows :
128+ navdata [sv_idx_key ] = np .nan
135129
136- func_satpos = np .empty ((3 ,), dtype = object )
137- func_satpos [:] = np .nan
138-
139- if method == 'CubicSpline' :
140- low_i = (sidx - ipos ) if (sidx - ipos ) >= 0 else 0
141- high_i = (sidx + ipos ) if (sidx + ipos ) <= len (sp3data ["gps_millis" ]) else - 1
130+ available_svs_from_sp3 = np .unique (self ["gnss_sv_id" ])
142131
132+ for gnss_sv_id in np .unique (navdata ["gnss_sv_id" ]):
143133 if verbose :
144- print ('Nearest sp3: ' , sidx , sp3data ["gps_millis" ][sidx ], \
145- sp3data ["x_sv_m" ][sidx ],
146- sp3data ["y_sv_m" ][sidx ],
147- sp3data ["z_sv_m" ][sidx ])
148-
149- func_satpos [0 ] = interpolate .CubicSpline (sp3data ["gps_millis" ][low_i :high_i ], \
150- sp3data ["x_sv_m" ][low_i :high_i ])
151- func_satpos [1 ] = interpolate .CubicSpline (sp3data ["gps_millis" ][low_i :high_i ], \
152- sp3data ["y_sv_m" ][low_i :high_i ])
153- func_satpos [2 ] = interpolate .CubicSpline (sp3data ["gps_millis" ][low_i :high_i ], \
154- sp3data ["z_sv_m" ][low_i :high_i ])
155-
156- return func_satpos
157-
158-
159- def sp3_snapshot (self , func_satpos , cxtime , hstep = 5e-1 ,
160- method = 'CubicSpline' ):
161- """Compute satellite 3D position and velocity.
162-
163- Computes from the sp3 interpolated function.
164-
165- Parameters
166- ----------
167- func_satpos : np.ndarray
168- Instance with 3-D array of scipy.interpolate.interpolate.interp1d
169- that is loaded with .sp3 data.
170- cxtime : float
171- Time at which the satellite 3-D position and velocity needs to be
172- computed, given 3-D array of interpolated functions.
173- hstep : float
174- Step size in milliseconds used to computing 3-D velocity of any
175- given satellite using central differencing the default is 5e-1).
176- method : string
177- Type of interpolation method used for sp3 data (the default is
178- CubicSpline, which depicts third-order polynomial).
179-
180- Returns
181- -------
182- satpos_sp3 : 3-D array
183- Computed satellite position in ECEF frame (Earth's rotation not included)
184- satvel_sp3 : 3-D array
185- Computed satellite velocity in ECEF frame (Earth's rotation not included)
186- """
187- if method == 'CubicSpline' :
188- sat_x = func_satpos [0 ]([cxtime - 0.5 * hstep , cxtime , cxtime + 0.5 * hstep ])
189- sat_y = func_satpos [1 ]([cxtime - 0.5 * hstep , cxtime , cxtime + 0.5 * hstep ])
190- sat_z = func_satpos [2 ]([cxtime - 0.5 * hstep , cxtime , cxtime + 0.5 * hstep ])
191-
192- satpos_sp3 = np .array ([sat_x [1 ], sat_y [1 ], sat_z [1 ]])
193- satvel_sp3 = np .array ([ (sat_x [2 ]- sat_x [0 ]) / hstep , \
194- (sat_y [2 ]- sat_y [0 ]) / hstep , \
195- (sat_z [2 ]- sat_z [0 ]) / hstep ])
196-
197- return satpos_sp3 , (satvel_sp3 * 1e3 )
134+ print ("interpolating sp3 for " ,gnss_sv_id )
135+ navdata_id = navdata .where ("gnss_sv_id" ,gnss_sv_id )
136+ navdata_id_gps_millis = np .atleast_1d (navdata_id ["gps_millis" ])
137+
138+ if gnss_sv_id in available_svs_from_sp3 :
139+ sp3_id = self .where ("gnss_sv_id" ,gnss_sv_id )
140+ x_data = sp3_id ["gps_millis" ]
141+ y_data = sp3_id [["x_sv_m" ,"y_sv_m" ,"z_sv_m" ]]
142+
143+ if np .min (navdata_id_gps_millis ) < x_data [0 ] \
144+ or np .max (navdata_id_gps_millis ) > x_data [- 1 ]:
145+ raise RuntimeError ("sp3 data does not include " \
146+ + "appropriate times in measurement" \
147+ + " file for SV " ,gnss_sv_id )
148+
149+ xyz_sv_m = np .zeros ((6 ,len (navdata_id )))
150+
151+ # iterate through needed polynomials so don't repeat fit
152+ insert_indexes = np .searchsorted (x_data ,navdata_id_gps_millis )
153+ for insert_index in np .unique (insert_indexes ):
154+ max_index = min (len (sp3_id )- 1 ,insert_index + int (window / 2 ))
155+ min_index = max (0 ,insert_index - int (window / 2 ))
156+ x_window = x_data [min_index :max_index ]
157+ y_window = y_data [:,min_index :max_index ]
158+
159+ insert_index_idxs = np .argwhere (insert_indexes == insert_index )
160+ x_interpret = navdata_id_gps_millis [insert_index_idxs ]
161+
162+ # iterate through x,y, and z
163+ for xyz_index in range (3 ):
164+ poly = np .polynomial .polynomial .Polynomial .fit (x_window , y_window [xyz_index ,:], deg = 3 )
165+ xyz_sv = poly (x_interpret )
166+
167+ polyder = poly .deriv ()
168+ vxyz_sv = polyder (x_interpret )
169+
170+ xyz_sv_m [xyz_index ,insert_index_idxs ] = xyz_sv
171+ # multiply by 1000 since currently meters/milliseconds
172+ xyz_sv_m [xyz_index + 3 ,insert_index_idxs ] = vxyz_sv * 1000
173+
174+ row_idx = navdata .argwhere ("gnss_sv_id" ,gnss_sv_id )
175+ navdata ["x_sv_m" ,row_idx ] = xyz_sv_m [0 ,:]
176+ navdata ["y_sv_m" ,row_idx ] = xyz_sv_m [1 ,:]
177+ navdata ["z_sv_m" ,row_idx ] = xyz_sv_m [2 ,:]
178+ navdata ["vx_sv_mps" ,row_idx ] = xyz_sv_m [3 ,:]
179+ navdata ["vy_sv_mps" ,row_idx ] = xyz_sv_m [4 ,:]
180+ navdata ["vz_sv_mps" ,row_idx ] = xyz_sv_m [5 ,:]
0 commit comments