17
17
import numpy as np
18
18
import pyfftw
19
19
import cPickle
20
- import defaults
21
20
22
21
from include .generateCAcode import caCodes
22
+ from include .generateGLOcode import GLOCode
23
+ from peregrine .gps_constants import L1CA
24
+ from peregrine .glo_constants import GLO_L1 , glo_l1_step
23
25
24
26
import logging
25
27
logger = logging .getLogger (__name__ )
@@ -191,13 +193,15 @@ def interpolate(self, S_0, S_1, S_2, interpolation='gaussian'):
191
193
192
194
**Parabolic interpolation:**
193
195
194
- .. math:: \Delta = \\ frac{1}{2} \\ frac{S[k+1] - S[k-1]}{2S[k] - S[k-1] - S[k+1]}
196
+ .. math:: \Delta = \\ frac{1}{2} \\ frac{S[k+1] -
197
+ S[k-1]}{2S[k] - S[k-1] - S[k+1]}
195
198
196
199
Where :math:`S[n]` is the magnitude of FFT bin :math:`n`.
197
200
198
201
**Gaussian interpolation:**
199
202
200
- .. math:: \Delta = \\ frac{1}{2} \\ frac{\ln(S[k+1]) - \ln(S[k-1])}{2\ln(S[k]) - \ln(S[k-1]) - \ln(S[k+1])}
203
+ .. math:: \Delta = \\ frac{1}{2} \\ frac{\ln(S[k+1]) -
204
+ \ln(S[k-1])}{2\ln(S[k]) - \ln(S[k-1]) - \ln(S[k+1])}
201
205
202
206
The Gaussian interpolation method gives better results, especially when
203
207
used with a Gaussian window function, at the expense of computational
@@ -342,6 +346,8 @@ def find_peak(self, freqs, results, interpolation='gaussian'):
342
346
freq_index , cp_samples = np .unravel_index (results .argmax (),
343
347
results .shape )
344
348
349
+ code_phase = float (cp_samples ) / self .samples_per_chip
350
+
345
351
if freq_index > 1 and freq_index < len (freqs ) - 1 :
346
352
delta = self .interpolate (
347
353
results [freq_index - 1 ][cp_samples ],
@@ -358,8 +364,6 @@ def find_peak(self, freqs, results, interpolation='gaussian'):
358
364
else :
359
365
freq = freqs [freq_index ]
360
366
361
- code_phase = float (cp_samples ) / self .samples_per_chip
362
-
363
367
# Calculate SNR for the peak.
364
368
results_mean = np .mean (results )
365
369
if results_mean != 0 :
@@ -370,7 +374,8 @@ def find_peak(self, freqs, results, interpolation='gaussian'):
370
374
return (code_phase , freq , snr )
371
375
372
376
def acquisition (self ,
373
- prns = range (32 ),
377
+ prns = xrange (32 ),
378
+ channels = [x - 7 for x in xrange (14 )],
374
379
doppler_priors = None ,
375
380
doppler_search = 7000 ,
376
381
doppler_step = None ,
@@ -379,10 +384,10 @@ def acquisition(self,
379
384
multi = True
380
385
):
381
386
"""
382
- Perform an acquisition for a given list of PRNs.
387
+ Perform an acquisition for a given list of PRNs/channels .
383
388
384
- Perform an acquisition for a given list of PRNs across a range of Doppler
385
- frequencies.
389
+ Perform an acquisition for a given list of PRNs/channels across a range of
390
+ Doppler frequencies.
386
391
387
392
This function returns :class:`AcquisitionResult` objects containing the
388
393
location of the acquisition peak for PRNs that have an acquisition
@@ -394,8 +399,13 @@ def acquisition(self,
394
399
395
400
Parameters
396
401
----------
402
+ bandcode : optional
403
+ String defining the acquisition code. Default: L1CA
404
+ choices: L1CA, GLO_L1 (in gps_constants.py)
397
405
prns : iterable, optional
398
406
List of PRNs to acquire. Default: 0..31 (0-indexed)
407
+ channels : iterable, optional
408
+ List of channels to acquire. Default: -7..6
399
409
doppler_prior: list of floats, optional
400
410
List of expected Doppler frequencies in Hz (one per PRN). Search will be
401
411
centered about these. If None, will search around 0 for all PRNs.
@@ -413,10 +423,11 @@ def acquisition(self,
413
423
Returns
414
424
-------
415
425
out : [AcquisitionResult]
416
- A list of :class:`AcquisitionResult` objects, one per PRN in `prns`.
426
+ A list of :class:`AcquisitionResult` objects, one per PRN in `prns` or
427
+ channel in 'channels'.
417
428
418
429
"""
419
- logger .info ("Acquisition starting" )
430
+ logger .info ("Acquisition starting for " + self . signal )
420
431
from peregrine .parallel_processing import parmap
421
432
422
433
# If the Doppler step is not specified, compute it from the coarse
@@ -428,9 +439,6 @@ def acquisition(self,
428
439
# magnitude.
429
440
doppler_step = self .sampling_freq / self .n_integrate
430
441
431
- if doppler_priors is None :
432
- doppler_priors = np .zeros_like (prns )
433
-
434
442
if progress_bar_output == 'stdout' :
435
443
show_progress = True
436
444
progress_fd = sys .stdout
@@ -446,33 +454,55 @@ def acquisition(self,
446
454
show_progress = False
447
455
logger .warning ("show_progress = True but progressbar module not found." )
448
456
457
+ if self .signal == L1CA :
458
+ input_len = len (prns )
459
+ offset = 1
460
+ pb_attr = progressbar .Attribute ('prn' , '(PRN: %02d)' , '(PRN --)' )
461
+ if doppler_priors is None :
462
+ doppler_priors = np .zeros_like (prns )
463
+ else :
464
+ input_len = len (channels )
465
+ offset = 0
466
+ pb_attr = progressbar .Attribute ('ch' , '(CH: %02d)' , '(CH --)' )
467
+ if doppler_priors is None :
468
+ doppler_priors = np .zeros_like (channels )
469
+
449
470
# Setup our progress bar if we need it
450
471
if show_progress and not multi :
451
472
widgets = [' Acquisition ' ,
452
- progressbar . Attribute ( 'prn' , '(PRN: %02d)' , '(PRN --)' ) , ' ' ,
473
+ pb_attr , ' ' ,
453
474
progressbar .Percentage (), ' ' ,
454
475
progressbar .ETA (), ' ' ,
455
476
progressbar .Bar ()]
456
477
pbar = progressbar .ProgressBar (widgets = widgets ,
457
- maxval = int (len ( prns ) *
458
- (2 * doppler_search / doppler_step + 1 )),
478
+ maxval = int (input_len *
479
+ (2 * doppler_search / doppler_step + 1 )),
459
480
fd = progress_fd )
460
481
pbar .start ()
461
482
else :
462
483
pbar = None
463
484
464
485
def do_acq (n ):
465
- prn = prns [n ]
486
+ if self .signal == L1CA :
487
+ prn = prns [n ]
488
+ code = caCodes [prn ]
489
+ int_f = self .IF
490
+ attr = {'prn' : prn + 1 }
491
+ else :
492
+ ch = channels [n ]
493
+ code = GLOCode
494
+ int_f = self .IF + ch * glo_l1_step
495
+ attr = {'ch' : ch }
466
496
doppler_prior = doppler_priors [n ]
467
497
freqs = np .arange (doppler_prior - doppler_search ,
468
- doppler_prior + doppler_search , doppler_step ) + self . IF
498
+ doppler_prior + doppler_search , doppler_step ) + int_f
469
499
if pbar :
470
500
def progress_callback (freq_num , num_freqs ):
471
- pbar .update (n * len (freqs ) + freq_num , attr = { 'prn' : prn + 1 } )
501
+ pbar .update (n * len (freqs ) + freq_num , attr = attr )
472
502
else :
473
503
progress_callback = None
474
504
475
- coarse_results = self .acquire (caCodes [ prn ] , freqs ,
505
+ coarse_results = self .acquire (code , freqs ,
476
506
progress_callback = progress_callback )
477
507
478
508
code_phase , carr_freq , snr = self .find_peak (freqs , coarse_results ,
@@ -485,13 +515,22 @@ def progress_callback(freq_num, num_freqs):
485
515
status = 'A'
486
516
487
517
# Save properties of the detected satellite signal
488
- acq_result = AcquisitionResult (prn ,
489
- carr_freq ,
490
- carr_freq - self .IF ,
491
- code_phase ,
492
- snr ,
493
- status ,
494
- self .signal )
518
+ if self .signal == L1CA :
519
+ acq_result = AcquisitionResult (prn ,
520
+ carr_freq ,
521
+ carr_freq - int_f ,
522
+ code_phase ,
523
+ snr ,
524
+ status ,
525
+ L1CA )
526
+ else :
527
+ acq_result = GloAcquisitionResult (ch ,
528
+ carr_freq ,
529
+ carr_freq - int_f ,
530
+ code_phase ,
531
+ snr ,
532
+ status ,
533
+ GLO_L1 )
495
534
496
535
# If the acquisition was successful, log it
497
536
if (snr > threshold ):
@@ -501,9 +540,9 @@ def progress_callback(freq_num, num_freqs):
501
540
502
541
if multi :
503
542
acq_results = parmap (
504
- do_acq , range ( len ( prns ) ), show_progress = show_progress )
543
+ do_acq , xrange ( input_len ), show_progress = show_progress )
505
544
else :
506
- acq_results = map (do_acq , range ( len ( prns ) ))
545
+ acq_results = map (do_acq , xrange ( input_len ))
507
546
508
547
# Acquisition is finished
509
548
@@ -512,9 +551,11 @@ def progress_callback(freq_num, num_freqs):
512
551
pbar .finish ()
513
552
514
553
logger .info ("Acquisition finished" )
515
- acquired_prns = [ar .prn + 1 for ar in acq_results if ar .status == 'A' ]
516
- logger .info ("Acquired %d satellites, PRNs: %s." ,
517
- len (acquired_prns ), acquired_prns )
554
+ acq = [ar .prn + offset for ar in acq_results if ar .status == 'A' ]
555
+ if self .signal == L1CA :
556
+ logger .info ("Acquired %d satellites, PRNs: %s." , len (acq ), acq )
557
+ else :
558
+ logger .info ("Acquired %d channels: %s." , len (acq ), acq )
518
559
519
560
return acq_results
520
561
@@ -531,7 +572,7 @@ def save_wisdom(self, wisdom_file=DEFAULT_WISDOM_FILE):
531
572
pyfftw .export_wisdom (), f , protocol = cPickle .HIGHEST_PROTOCOL )
532
573
533
574
534
- class AcquisitionResult :
575
+ class AcquisitionResult ( object ) :
535
576
"""
536
577
Stores the acquisition parameters of a single satellite.
537
578
@@ -560,7 +601,7 @@ class AcquisitionResult:
560
601
"""
561
602
562
603
__slots__ = ('prn' , 'carr_freq' , 'doppler' ,
563
- 'code_phase' , 'snr' , 'status' , 'signal' )
604
+ 'code_phase' , 'snr' , 'status' , 'signal' , 'sample_index' )
564
605
565
606
def __init__ (self , prn , carr_freq , doppler , code_phase , snr , status , signal ,
566
607
sample_index = 0 ):
@@ -574,7 +615,7 @@ def __init__(self, prn, carr_freq, doppler, code_phase, snr, status, signal,
574
615
self .sample_index = sample_index
575
616
576
617
def __str__ (self ):
577
- return "PRN %2d (%s) SNR %6.2f @ CP %6.1f , %+8.2f Hz %s" % \
618
+ return "PRN %2d (%s) SNR %6.2f @ CP %6.3f , %+8.2f Hz %s" % \
578
619
(self .prn + 1 , self .signal , self .snr , self .code_phase ,
579
620
self .doppler , self .status )
580
621
@@ -615,6 +656,20 @@ def _equal(self, other):
615
656
return True
616
657
617
658
659
+ class GloAcquisitionResult (AcquisitionResult ):
660
+
661
+ def __init__ (self , channel , carr_freq , doppler , code_phase , snr , status ,
662
+ signal , sample_index = 0 ):
663
+ super (GloAcquisitionResult , self ).__init__ (channel , carr_freq , doppler ,
664
+ code_phase , snr , status ,
665
+ signal , sample_index )
666
+
667
+ def __str__ (self ):
668
+ return "CH %2d (%s) SNR %6.2f @ CP %6.3f, %+8.2f Hz %s" % \
669
+ (self .prn , self .signal , self .snr , self .code_phase , self .doppler ,
670
+ self .status )
671
+
672
+
618
673
def save_acq_results (filename , acq_results ):
619
674
"""
620
675
Save a set of acquisition results to a file.
@@ -676,4 +731,5 @@ def print_scores(acq_results, pred, pred_dopp=None):
676
731
677
732
print "Found %d of %d, mean doppler error = %+5.0f Hz, mean abs err = %4.0f Hz, worst = %+5.0f Hz" \
678
733
% (n_match , len (pred ),
679
- sum_dopp_err / max (1 , n_match ), sum_abs_dopp_err / max (1 , n_match ), worst_dopp_err )
734
+ sum_dopp_err / max (1 , n_match ), sum_abs_dopp_err /
735
+ max (1 , n_match ), worst_dopp_err )
0 commit comments