2525from swiftnav .signal import signal_from_code_index
2626from peregrine import defaults
2727from peregrine import gps_constants
28+ from peregrine import glo_constants
2829from peregrine import alias_detector
2930from peregrine .acquisition import AcquisitionResult
31+ from peregrine .acquisition import GloAcquisitionResult
3032from peregrine .include .generateCAcode import caCodes
3133from peregrine .include .generateL2CMcode import L2CMCodes
34+ from peregrine .include .generateGLOcode import GLOCode
3235from peregrine .tracking_file_utils import createTrackingOutputFileNames
3336
3437import logging
@@ -120,6 +123,8 @@ def _tracking_channel_factory(parameters):
120123 return TrackingChannelL1CA (parameters )
121124 if parameters ['acq' ].signal == gps_constants .L2C :
122125 return TrackingChannelL2C (parameters )
126+ if parameters ['acq' ].signal == glo_constants .GLO_L1 :
127+ return TrackingChannelGLOL1 (parameters )
123128
124129
125130class TrackingChannel (object ):
@@ -686,6 +691,7 @@ def _run_postprocess(self):
686691
687692 # Handover to L2C if possible
688693 if self .l2c_handover and not self .l2c_handover_acq and \
694+ gps_constants .L2C in self .samples and \
689695 'samples' in self .samples [gps_constants .L2C ] and sync :
690696 chan_snr = self .track_result .cn0 [self .i ]
691697 chan_snr -= 10 * np .log10 (defaults .L1CA_CHANNEL_BANDWIDTH_HZ )
@@ -808,6 +814,139 @@ def _run_postprocess(self):
808814 self .coherent_ms
809815
810816
817+ class TrackingChannelGLOL1 (TrackingChannel ):
818+ """
819+ GLO L1 tracking channel.
820+ """
821+
822+ def __init__ (self , params ):
823+ """
824+ Initialize GLO L1 tracking channel with GLO L1 specific data.
825+
826+ Parameters
827+ ----------
828+ params : dictionary
829+ GLO L1 tracking initialization parameters
830+
831+ """
832+ # Convert acquisition SNR to C/N0
833+ cn0_0 = 10 * np .log10 (params ['acq' ].snr )
834+ cn0_0 += 10 * np .log10 (defaults .GLOL1_CHANNEL_BANDWIDTH_HZ )
835+ params ['cn0_0' ] = cn0_0
836+ params ['coherent_ms' ] = 1
837+ params ['coherent_iter' ] = 1
838+ params ['loop_filter_params' ] = defaults .l1ca_stage1_loop_filter_params
839+ params ['lock_detect_params' ] = defaults .l1ca_lock_detect_params_opt
840+ params ['IF' ] = params ['samples' ][glo_constants .GLO_L1 ]['IF' ]
841+ params ['prn_code' ] = GLOCode
842+ params ['code_freq_init' ] = params ['acq' ].doppler * \
843+ glo_constants .glo_chip_rate / glo_constants .glo_l1
844+ params ['chipping_rate' ] = glo_constants .glo_chip_rate
845+ params ['sample_index' ] = 0
846+ params ['alias_detector' ] = \
847+ alias_detector .AliasDetectorGLO (params ['coherent_ms' ])
848+
849+ TrackingChannel .__init__ (self , params )
850+
851+ self .glol2_handover_acq = None
852+ self .glol2_handover_done = False
853+
854+ # TODO add nav msg decoder (GLO L1)
855+
856+ def is_pickleable (self ):
857+ """
858+ GLO L1 tracking channel object is not pickleable due to complexity
859+ of serializing cnav_msg_decoder Cython object.
860+
861+ out : bool
862+ False - the GLO L1 tracking object is not pickleable
863+ """
864+ return False
865+
866+ def _get_result (self ):
867+ """
868+ Get GLO L1 tracking results.
869+ The possible outcome of GLO L1 tracking operation is
870+ the GLO L1 handover to GLO L2 in the form of an GloAcquisitionResult object.
871+
872+ Returns
873+ -------
874+ out : AcquisitionResult
875+ GLO L2 acquisition result or None
876+
877+ """
878+
879+ if self .glol2_handover_acq and not self .glol2_handover_done :
880+ self .glol2_handover_done = True
881+ return self .glol2_handover_acq
882+ return None
883+
884+ def _run_preprocess (self ):
885+ """
886+ Run GLONASS tracking loop preprocessor operation.
887+ It runs before every coherent integration round.
888+
889+ """
890+
891+ self .coherent_iter = self .coherent_ms
892+
893+ def _short_n_long_preprocess (self ):
894+ if self .stage1 :
895+ self .E = self .P = self .L = 0.j
896+ else :
897+ # When simulating short and long cycles, short step resets EPL
898+ # registers, and long one adds up to them
899+ if self .short_step :
900+ self .E = self .P = self .L = 0.j
901+ self .coherent_iter = 1
902+ else :
903+ self .coherent_iter = self .coherent_ms - 1
904+
905+ self .code_chips_to_integrate = glo_constants .glo_code_len
906+
907+ return self .coherent_iter , self .code_chips_to_integrate
908+
909+ def _short_n_long_postprocess (self ):
910+ more_integration_needed = False
911+ if not self .stage1 :
912+ if self .short_step :
913+ # In case of short step - go to next integration period
914+ self .short_step = False
915+ more_integration_needed = True
916+ else :
917+ # Next step is short cycle
918+ self .short_step = True
919+ return more_integration_needed
920+
921+ def _run_postprocess (self ):
922+ """
923+ Run GLO L1 coherent integration postprocessing.
924+ Runs navigation bit sync decoding operation and
925+ GLO L1 to GLO L2 handover.
926+ """
927+
928+ # Handover to L2C if possible
929+ if self .glol2_handover and not self .glol2_handover_acq and \
930+ glo_constants .GLO_L2 in self .samples and \
931+ 'samples' in self .samples [glo_constants .GLO_L2 ]: # and sync:
932+ chan_snr = self .track_result .cn0 [self .i ]
933+ # chan_snr -= 10 * np.log10(defaults.GLOL1_CHANNEL_BANDWIDTH_HZ)
934+ chan_snr = np .power (10 , chan_snr / 10 )
935+ glol2_doppler = self .loop_filter .to_dict ()['carr_freq' ] * \
936+ glo_constants .glo_l2 / glo_constants .glo_l1
937+ self .glol2_handover_acq = \
938+ GloAcquisitionResult (self .prn ,
939+ self .samples [glo_constants .GLO_L2 ]['IF' ] +
940+ glol2_doppler ,
941+ glol2_doppler , # carrier doppler
942+ self .track_result .code_phase [
943+ self .i ],
944+ chan_snr ,
945+ 'A' ,
946+ glo_constants .GLO_L2 ,
947+ self .track_result .absolute_sample [self .i ])
948+
949+
811950class Tracker (object ):
812951 """
813952 Tracker class.
@@ -822,6 +961,7 @@ def __init__(self,
822961 sampling_freq ,
823962 check_l2c_mask = False ,
824963 l2c_handover = True ,
964+ glol2_handover = True ,
825965 progress_bar_output = 'none' ,
826966 loop_filter_class = AidedTrackingLoop ,
827967 correlator = track_correlate ,
@@ -877,6 +1017,7 @@ def __init__(self,
8771017 self .tracker_options = tracker_options
8781018 self .output_file = output_file
8791019 self .l2c_handover = l2c_handover
1020+ self .glol2_handover = glol2_handover
8801021 self .check_l2c_mask = check_l2c_mask
8811022 self .correlator = correlator
8821023 self .stage2_coherent_ms = stage2_coherent_ms
@@ -1021,6 +1162,7 @@ def _create_channel(self, acq):
10211162 'samples_to_track' : self .samples_to_track ,
10221163 'sampling_freq' : self .sampling_freq ,
10231164 'l2c_handover' : l2c_handover ,
1165+ 'glol2_handover' : self .glol2_handover ,
10241166 'show_progress' : self .show_progress ,
10251167 'correlator' : self .correlator ,
10261168 'stage2_coherent_ms' : self .stage2_coherent_ms ,
0 commit comments