@@ -467,3 +467,51 @@ def ecef_to_el_az(rx_pos, sv_pos):
467467 el_az [:,1 ][el_az [:,1 ] < 0 ] += 360
468468
469469 return el_az
470+
471+ def add_el_az (navdata , receiver_state ):
472+ """Adds elevation and azimuth to NavData object.
473+
474+ Parameters
475+ ----------
476+ navdata : gnss_lib_py.parsers.navdata.NavData
477+ Instance of the NavData class. Must include ``gps_millis`` as
478+ well as satellite ECEF positions as ``x_sv_m``, ``y_sv_m``,
479+ ``z_sv_m``, ``gnss_id`` and ``sv_id``.
480+ receiver_state : gnss_lib_py.parsers.navdata.NavData
481+ Either estimated or ground truth receiver position in ECEF frame
482+ in meters as an instance of the NavData class with the
483+ following rows: ``x_*_m``, ``y_*_m``, ``z_*_m``, ``gps_millis``.
484+
485+ """
486+
487+ # check for missing rows
488+ navdata .in_rows (["gps_millis" ,"x_sv_m" ,"y_sv_m" ,"z_sv_m" ,
489+ "gnss_id" ,"sv_id" ])
490+ receiver_state .in_rows (["gps_millis" ])
491+
492+ # check for receiver_state indexes
493+ rx_idxs = receiver_state .find_wildcard_indexes (["x_*_m" ,"y_*_m" ,
494+ "z_*_m" ],max_allow = 1 )
495+
496+ sv_el_az = None
497+ for timestamp , _ , navdata_subset in navdata .loop_time ("gps_millis" ):
498+
499+ pos_sv_m = navdata_subset [["x_sv_m" ,"y_sv_m" ,"z_sv_m" ]].T
500+
501+ # find time index for receiver_state NavData instance
502+ rx_t_idx = np .argmin (np .abs (receiver_state ["gps_millis" ] - timestamp ))
503+
504+ pos_rx_m = receiver_state [[rx_idxs ["x_*_m" ][0 ],
505+ rx_idxs ["y_*_m" ][0 ],
506+ rx_idxs ["z_*_m" ][0 ]],
507+ rx_t_idx ].reshape (1 ,- 1 )
508+
509+ timestep_el_az = ecef_to_el_az (pos_rx_m , pos_sv_m )
510+
511+ if sv_el_az is None :
512+ sv_el_az = timestep_el_az .T
513+ else :
514+ sv_el_az = np .hstack ((sv_el_az ,timestep_el_az .T ))
515+
516+ navdata ["el_sv_deg" ] = sv_el_az [0 ,:]
517+ navdata ["az_sv_deg" ] = sv_el_az [1 ,:]
0 commit comments