Skip to content
This repository was archived by the owner on Apr 13, 2021. It is now read-only.

Commit cc4b127

Browse files
author
Pasi Miettinen
committed
GLO acquisition support
1 parent 09a118a commit cc4b127

File tree

7 files changed

+273
-110
lines changed

7 files changed

+273
-110
lines changed

peregrine/acquisition.py

Lines changed: 122 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
import numpy as np
1818
import pyfftw
1919
import cPickle
20-
import defaults
2120

2221
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
2325

2426
import logging
2527
logger = logging.getLogger(__name__)
@@ -191,13 +193,15 @@ def interpolate(self, S_0, S_1, S_2, interpolation='gaussian'):
191193
192194
**Parabolic interpolation:**
193195
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]}
195198
196199
Where :math:`S[n]` is the magnitude of FFT bin :math:`n`.
197200
198201
**Gaussian interpolation:**
199202
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])}
201205
202206
The Gaussian interpolation method gives better results, especially when
203207
used with a Gaussian window function, at the expense of computational
@@ -342,24 +346,39 @@ def find_peak(self, freqs, results, interpolation='gaussian'):
342346
freq_index, cp_samples = np.unravel_index(results.argmax(),
343347
results.shape)
344348

345-
if freq_index > 1 and freq_index < len(freqs) - 1:
346-
delta = self.interpolate(
347-
results[freq_index - 1][cp_samples],
348-
results[freq_index][cp_samples],
349-
results[freq_index + 1][cp_samples],
350-
interpolation
351-
)
352-
if delta > 0:
353-
freq = freqs[freq_index] + \
354-
(freqs[freq_index + 1] - freqs[freq_index]) * delta
355-
else:
356-
freq = freqs[freq_index] - \
357-
(freqs[freq_index - 1] - freqs[freq_index]) * delta
358-
else:
359-
freq = freqs[freq_index]
360-
361349
code_phase = float(cp_samples) / self.samples_per_chip
362350

351+
#print results[freq_index]
352+
#pp(results[freq_index - 6][cp_samples])
353+
#pp(results[freq_index - 5][cp_samples])
354+
#pp(results[freq_index - 4][cp_samples])
355+
#pp(results[freq_index - 3][cp_samples])
356+
#pp(results[freq_index - 2][cp_samples])
357+
#pp(results[freq_index - 1][cp_samples])
358+
#pp(results[freq_index][cp_samples])
359+
#pp(results[freq_index + 1][cp_samples])
360+
#pp(results[freq_index + 2][cp_samples])
361+
#pp(results[freq_index + 3][cp_samples])
362+
#pp(results[freq_index + 4][cp_samples])
363+
#pp(results[freq_index + 5][cp_samples])
364+
#pp(results[freq_index + 6][cp_samples])
365+
366+
#if freq_index > 3 and freq_index < len(freqs) - 3:
367+
#delta = self.interpolate(
368+
#results[freq_index - 3][cp_samples],
369+
#results[freq_index][cp_samples],
370+
#results[freq_index + 3][cp_samples],
371+
#interpolation
372+
#)
373+
#if delta > 0:
374+
#freq = freqs[freq_index] + \
375+
#(freqs[freq_index + 3] - freqs[freq_index]) * delta
376+
#else:
377+
#freq = freqs[freq_index] - \
378+
#(freqs[freq_index - 3] - freqs[freq_index]) * delta
379+
#else:
380+
freq = freqs[freq_index]
381+
363382
# Calculate SNR for the peak.
364383
results_mean = np.mean(results)
365384
if results_mean != 0:
@@ -370,7 +389,8 @@ def find_peak(self, freqs, results, interpolation='gaussian'):
370389
return (code_phase, freq, snr)
371390

372391
def acquisition(self,
373-
prns=range(32),
392+
prns=xrange(32),
393+
channels=[x - 7 for x in xrange(14)],
374394
doppler_priors=None,
375395
doppler_search=7000,
376396
doppler_step=None,
@@ -379,10 +399,10 @@ def acquisition(self,
379399
multi=True
380400
):
381401
"""
382-
Perform an acquisition for a given list of PRNs.
402+
Perform an acquisition for a given list of PRNs/channels.
383403
384-
Perform an acquisition for a given list of PRNs across a range of Doppler
385-
frequencies.
404+
Perform an acquisition for a given list of PRNs/channels across a range of
405+
Doppler frequencies.
386406
387407
This function returns :class:`AcquisitionResult` objects containing the
388408
location of the acquisition peak for PRNs that have an acquisition
@@ -394,8 +414,13 @@ def acquisition(self,
394414
395415
Parameters
396416
----------
417+
bandcode : optional
418+
String defining the acquisition code. Default: L1CA
419+
choices: L1CA, GLO_L1 (in gps_constants.py)
397420
prns : iterable, optional
398421
List of PRNs to acquire. Default: 0..31 (0-indexed)
422+
channels : iterable, optional
423+
List of channels to acquire. Default: -7..6
399424
doppler_prior: list of floats, optional
400425
List of expected Doppler frequencies in Hz (one per PRN). Search will be
401426
centered about these. If None, will search around 0 for all PRNs.
@@ -413,10 +438,11 @@ def acquisition(self,
413438
Returns
414439
-------
415440
out : [AcquisitionResult]
416-
A list of :class:`AcquisitionResult` objects, one per PRN in `prns`.
441+
A list of :class:`AcquisitionResult` objects, one per PRN in `prns` or
442+
channel in 'channels'.
417443
418444
"""
419-
logger.info("Acquisition starting")
445+
logger.info("Acquisition starting for " + self.signal)
420446
from peregrine.parallel_processing import parmap
421447

422448
# If the Doppler step is not specified, compute it from the coarse
@@ -428,9 +454,6 @@ def acquisition(self,
428454
# magnitude.
429455
doppler_step = self.sampling_freq / self.n_integrate
430456

431-
if doppler_priors is None:
432-
doppler_priors = np.zeros_like(prns)
433-
434457
if progress_bar_output == 'stdout':
435458
show_progress = True
436459
progress_fd = sys.stdout
@@ -446,33 +469,55 @@ def acquisition(self,
446469
show_progress = False
447470
logger.warning("show_progress = True but progressbar module not found.")
448471

472+
if self.signal == L1CA:
473+
input_len = len(prns)
474+
offset = 1
475+
pb_attr = progressbar.Attribute('prn', '(PRN: %02d)', '(PRN --)')
476+
if doppler_priors is None:
477+
doppler_priors = np.zeros_like(prns)
478+
else:
479+
input_len = len(channels)
480+
offset = 0
481+
pb_attr = progressbar.Attribute('ch', '(CH: %02d)', '(CH --)')
482+
if doppler_priors is None:
483+
doppler_priors = np.zeros_like(channels)
484+
449485
# Setup our progress bar if we need it
450486
if show_progress and not multi:
451487
widgets = [' Acquisition ',
452-
progressbar.Attribute('prn', '(PRN: %02d)', '(PRN --)'), ' ',
488+
pb_attr, ' ',
453489
progressbar.Percentage(), ' ',
454490
progressbar.ETA(), ' ',
455491
progressbar.Bar()]
456492
pbar = progressbar.ProgressBar(widgets=widgets,
457-
maxval=int(len(prns) *
458-
(2 * doppler_search / doppler_step + 1)),
493+
maxval=int(input_len *
494+
(2 * doppler_search / doppler_step + 1)),
459495
fd=progress_fd)
460496
pbar.start()
461497
else:
462498
pbar = None
463499

464500
def do_acq(n):
465-
prn = prns[n]
501+
if self.signal == L1CA:
502+
prn = prns[n]
503+
code = caCodes[prn]
504+
int_f = self.IF
505+
attr = {'prn': prn + 1}
506+
else:
507+
ch = channels[n]
508+
code = GLOCode
509+
int_f = self.IF + ch * glo_l1_step
510+
attr = {'ch': ch}
466511
doppler_prior = doppler_priors[n]
467512
freqs = np.arange(doppler_prior - doppler_search,
468-
doppler_prior + doppler_search, doppler_step) + self.IF
513+
doppler_prior + doppler_search, doppler_step) + int_f
469514
if pbar:
470515
def progress_callback(freq_num, num_freqs):
471-
pbar.update(n * len(freqs) + freq_num, attr={'prn': prn + 1})
516+
pbar.update(n * len(freqs) + freq_num, attr=attr)
472517
else:
473518
progress_callback = None
474519

475-
coarse_results = self.acquire(caCodes[prn], freqs,
520+
coarse_results = self.acquire(code, freqs,
476521
progress_callback=progress_callback)
477522

478523
code_phase, carr_freq, snr = self.find_peak(freqs, coarse_results,
@@ -485,13 +530,22 @@ def progress_callback(freq_num, num_freqs):
485530
status = 'A'
486531

487532
# 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)
533+
if self.signal == L1CA:
534+
acq_result = AcquisitionResult(prn,
535+
carr_freq,
536+
carr_freq - int_f,
537+
code_phase,
538+
snr,
539+
status,
540+
L1CA)
541+
else:
542+
acq_result = GloAcquisitionResult(ch,
543+
carr_freq,
544+
carr_freq - int_f,
545+
code_phase,
546+
snr,
547+
status,
548+
GLO_L1)
495549

496550
# If the acquisition was successful, log it
497551
if (snr > threshold):
@@ -501,9 +555,9 @@ def progress_callback(freq_num, num_freqs):
501555

502556
if multi:
503557
acq_results = parmap(
504-
do_acq, range(len(prns)), show_progress=show_progress)
558+
do_acq, xrange(input_len), show_progress=show_progress)
505559
else:
506-
acq_results = map(do_acq, range(len(prns)))
560+
acq_results = map(do_acq, xrange(input_len))
507561

508562
# Acquisition is finished
509563

@@ -512,9 +566,11 @@ def progress_callback(freq_num, num_freqs):
512566
pbar.finish()
513567

514568
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)
569+
acq = [ar.prn + offset for ar in acq_results if ar.status == 'A']
570+
if self.signal == L1CA:
571+
logger.info("Acquired %d satellites, PRNs: %s.", len(acq), acq)
572+
else:
573+
logger.info("Acquired %d channels: %s.", len(acq), acq)
518574

519575
return acq_results
520576

@@ -531,7 +587,7 @@ def save_wisdom(self, wisdom_file=DEFAULT_WISDOM_FILE):
531587
pyfftw.export_wisdom(), f, protocol=cPickle.HIGHEST_PROTOCOL)
532588

533589

534-
class AcquisitionResult:
590+
class AcquisitionResult(object):
535591
"""
536592
Stores the acquisition parameters of a single satellite.
537593
@@ -560,7 +616,7 @@ class AcquisitionResult:
560616
"""
561617

562618
__slots__ = ('prn', 'carr_freq', 'doppler',
563-
'code_phase', 'snr', 'status', 'signal')
619+
'code_phase', 'snr', 'status', 'signal', 'sample_index')
564620

565621
def __init__(self, prn, carr_freq, doppler, code_phase, snr, status, signal,
566622
sample_index=0):
@@ -574,7 +630,7 @@ def __init__(self, prn, carr_freq, doppler, code_phase, snr, status, signal,
574630
self.sample_index = sample_index
575631

576632
def __str__(self):
577-
return "PRN %2d (%s) SNR %6.2f @ CP %6.1f, %+8.2f Hz %s" % \
633+
return "PRN %2d (%s) SNR %6.2f @ CP %6.3f, %+8.2f Hz %s" % \
578634
(self.prn + 1, self.signal, self.snr, self.code_phase,
579635
self.doppler, self.status)
580636

@@ -615,6 +671,20 @@ def _equal(self, other):
615671
return True
616672

617673

674+
class GloAcquisitionResult(AcquisitionResult):
675+
676+
def __init__(self, channel, carr_freq, doppler, code_phase, snr, status,
677+
signal, sample_index=0):
678+
super(GloAcquisitionResult, self).__init__(channel, carr_freq, doppler,
679+
code_phase, snr, status,
680+
signal, sample_index)
681+
682+
def __str__(self):
683+
return "CH %2d (%s) SNR %6.2f @ CP %6.3f, %+8.2f Hz %s" % \
684+
(self.prn, self.signal, self.snr, self.code_phase, self.doppler,
685+
self.status)
686+
687+
618688
def save_acq_results(filename, acq_results):
619689
"""
620690
Save a set of acquisition results to a file.
@@ -676,4 +746,5 @@ def print_scores(acq_results, pred, pred_dopp=None):
676746

677747
print "Found %d of %d, mean doppler error = %+5.0f Hz, mean abs err = %4.0f Hz, worst = %+5.0f Hz"\
678748
% (n_match, len(pred),
679-
sum_dopp_err / max(1, n_match), sum_abs_dopp_err / max(1, n_match), worst_dopp_err)
749+
sum_dopp_err / max(1, n_match), sum_abs_dopp_err /
750+
max(1, n_match), worst_dopp_err)

peregrine/defaults.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
ephemMaxAge = 4 * 3600.0 # Reject an ephemeris entry if older than this
1818

1919
# the size of the sample data block processed at a time
20-
processing_block_size = 20e6 # [samples]
20+
processing_block_size = 20e6 # [samples]
2121

2222
# original
2323
sample_channel_GPS_L1 = 0
@@ -75,18 +75,21 @@
7575
freq_profile_low_rate = {
7676
'GPS_L1_IF': 14.58e5,
7777
'GPS_L2_IF': 7.4e5,
78+
'GLO_L1_IF': 12e5,
7879
'sampling_freq': 24.84375e5}
7980

8081
# 'normal_rate' frequencies profile
8182
freq_profile_normal_rate = {
8283
'GPS_L1_IF': 14.58e6,
8384
'GPS_L2_IF': 7.4e6,
85+
'GLO_L1_IF': 12e6,
8486
'sampling_freq': 24.84375e6}
8587

86-
# 'normal_rate' frequencies profile
88+
# 'high_rate' frequencies profile
8789
freq_profile_high_rate = {
8890
'GPS_L1_IF': freq_profile_normal_rate['GPS_L1_IF'],
8991
'GPS_L2_IF': freq_profile_normal_rate['GPS_L2_IF'],
92+
'GLO_L1_IF': freq_profile_normal_rate['GLO_L1_IF'],
9093
'sampling_freq': 99.375e6}
9194

9295
L1CA_CHANNEL_BANDWIDTH_HZ = 1000

peregrine/glo_constants.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
from gps_constants import c
3+
# GLO system parameters
4+
glo_l1 = 1.602e9 # Hz
5+
glo_l2 = 1.246e9 # Hz
6+
glo_code_len = 511
7+
glo_chip_rate = 0.511e6 # Hz
8+
glo_l1_step = 0.5625e6 # Hz
9+
10+
glo_code_period = glo_code_len / glo_chip_rate
11+
glo_code_wavelength = glo_code_period * c
12+
13+
GLO_L1 = 'glo_l1'

0 commit comments

Comments
 (0)