track.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Swift Navigation Inc.
00003  * Contact: Fergus Noble <fergus@swift-nav.com>
00004  *
00005  * This source is subject to the license found in the file 'LICENSE' which must
00006  * be be distributed together with this source. All other rights reserved.
00007  *
00008  * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
00009  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
00010  * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
00011  */
00012 
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <math.h>
00016 #include <float.h>
00017 
00018 #include "constants.h"
00019 #include "prns.h"
00020 #include "track.h"
00021 #include "ephemeris.h"
00022 #include "tropo.h"
00023 #include "coord_system.h"
00024 
00103 void calc_loop_gains(float bw, float zeta, float k, float loop_freq,
00104                      float *pgain, float *igain)
00105 {
00106   /* Find the natural frequency. */
00107   float omega_n = 8.f*bw*zeta / (4.f*zeta*zeta + 1.f);
00108 
00109   /* Some intermmediate values. */
00110 /*
00111   float T = 1. / loop_freq;
00112   float denominator = k*(4 + 4*zeta*omega_n*T + omega_n*omega_n*T*T);
00113 
00114   *pgain = 8*zeta*omega_n*T / denominator;
00115   *igain = 4*omega_n*omega_n*T*T / denominator;
00116 */
00117   *igain = omega_n * omega_n / (k * loop_freq);
00118   *pgain = 2.f * zeta * omega_n / k;
00119 }
00120 
00139 float costas_discriminator(float I, float Q)
00140 {
00141   if (I == 0) {
00142     // Technically, it should be +/- 0.25, but then we'd have to keep track
00143     //  of the previous sign do it right, so it's simple enough to just return
00144     //  the average of 0.25 and -0.25 in the face of that ambiguity, so zero.
00145     return 0; 
00146   }
00147   return atanf(Q / I) * (float)(1/(2*M_PI));
00148 }
00149 
00174 float frequency_discriminator(float I, float Q, float prev_I, float prev_Q)
00175 {
00176   float dot = fabsf(I * prev_I) + fabsf(Q * prev_Q);
00177   float cross = prev_I * Q - I * prev_Q;
00178   return atan2f(cross, dot) / ((float) M_PI);
00179 }
00180 
00207 float dll_discriminator(correlation_t cs[3])
00208 {
00209   float early_mag = sqrtf((float)cs[0].I*cs[0].I + (float)cs[0].Q*cs[0].Q);
00210   float late_mag = sqrtf((float)cs[2].I*cs[2].I + (float)cs[2].Q*cs[2].Q);
00211 
00212   return 0.5f * (early_mag - late_mag) / (early_mag + late_mag);
00213 }
00214 
00225 void aided_lf_init(aided_lf_state_t *s, float y0,
00226                    float pgain, float igain,
00227                    float aiding_igain)
00228 {
00229   s->y = y0;
00230   s->prev_error = 0.f;
00231   s->pgain = pgain;
00232   s->igain = igain;
00233   s->aiding_igain = aiding_igain;
00234 }
00235 
00245 float aided_lf_update(aided_lf_state_t *s, float p_i_error, float aiding_error)
00246 {
00247   s->y += s->pgain * (p_i_error - s->prev_error) + \
00248           s->igain * p_i_error + \
00249           s->aiding_igain * aiding_error;
00250   s->prev_error = p_i_error;
00251 
00252   return s->y;
00253 }
00254 
00263 void simple_lf_init(simple_lf_state_t *s, float y0,
00264                     float pgain, float igain)
00265 {
00266   s->y = y0;
00267   s->prev_error = 0.f;
00268   s->pgain = pgain;
00269   s->igain = igain;
00270 }
00271 
00288 float simple_lf_update(simple_lf_state_t *s, float error)
00289 {
00290   s->y += s->pgain * (error - s->prev_error) + \
00291           s->igain * error;
00292   s->prev_error = error;
00293 
00294   return s->y;
00295 }
00296 
00313 void aided_tl_init(aided_tl_state_t *s, float loop_freq,
00314                    float code_freq, float code_bw,
00315                    float code_zeta, float code_k,
00316                    float carr_freq, float carr_bw,
00317                    float carr_zeta, float carr_k,
00318                    float carr_freq_igain)
00319 {
00320   float pgain, igain;
00321 
00322   s->carr_freq = carr_freq;
00323   s->prev_I = 1.0f; // This works, but is it a really good way to do it?
00324   s->prev_Q = 0.0f;
00325   calc_loop_gains(carr_bw, carr_zeta, carr_k, loop_freq, &pgain, &igain);
00326   aided_lf_init(&(s->carr_filt), carr_freq, pgain, igain, carr_freq_igain);
00327 
00328   calc_loop_gains(code_bw, code_zeta, code_k, loop_freq, &pgain, &igain);
00329   s->code_freq = code_freq;
00330   simple_lf_init(&(s->code_filt), code_freq, pgain, igain);
00331 }
00332 
00350 void aided_tl_update(aided_tl_state_t *s, correlation_t cs[3])
00351 {
00352   float carr_error = costas_discriminator(cs[1].I, cs[1].Q);
00353   float freq_error = frequency_discriminator(cs[1].I, cs[1].Q, s->prev_I, s->prev_Q);
00354   s->prev_I = cs[1].I;
00355   s->prev_Q = cs[1].Q;
00356   s->carr_freq = aided_lf_update(&(s->carr_filt), carr_error, freq_error);
00357 
00358   float code_error = dll_discriminator(cs);
00359   s->code_freq = simple_lf_update(&(s->code_filt), -code_error); // + s->carr_freq * SCALING_FACTOR
00360 }
00361 
00376 void simple_tl_init(simple_tl_state_t *s, float loop_freq,
00377                     float code_freq, float code_bw,
00378                     float code_zeta, float code_k,
00379                     float carr_freq, float carr_bw,
00380                     float carr_zeta, float carr_k)
00381 {
00382   float pgain, igain;
00383 
00384   calc_loop_gains(code_bw, code_zeta, code_k, loop_freq, &pgain, &igain);
00385   s->code_freq = code_freq;
00386   simple_lf_init(&(s->code_filt), code_freq, pgain, igain);
00387 
00388   calc_loop_gains(carr_bw, carr_zeta, carr_k, loop_freq, &pgain, &igain);
00389   s->carr_freq = carr_freq;
00390   simple_lf_init(&(s->carr_filt), carr_freq, pgain, igain);
00391 }
00392 
00407 void simple_tl_update(simple_tl_state_t *s, correlation_t cs[3])
00408 {
00409   float code_error = dll_discriminator(cs);
00410   s->code_freq = simple_lf_update(&(s->code_filt), -code_error);
00411   float carr_error = costas_discriminator(cs[1].I, cs[1].Q);
00412   s->carr_freq = simple_lf_update(&(s->carr_filt), carr_error);
00413 }
00414 
00444 void comp_tl_init(comp_tl_state_t *s, float loop_freq,
00445                   float code_freq, float code_bw,
00446                   float code_zeta, float code_k,
00447                   float carr_freq, float carr_bw,
00448                   float carr_zeta, float carr_k,
00449                   float tau, float cpc,
00450                   u32 sched)
00451 {
00452   float pgain, igain;
00453 
00454   calc_loop_gains(code_bw, code_zeta, code_k, loop_freq, &pgain, &igain);
00455   s->code_freq = code_freq;
00456   simple_lf_init(&(s->code_filt), code_freq, pgain, igain);
00457 
00458   calc_loop_gains(carr_bw, carr_zeta, carr_k, loop_freq, &pgain, &igain);
00459   s->carr_freq = carr_freq;
00460   simple_lf_init(&(s->carr_filt), carr_freq, pgain, igain);
00461 
00462   s->n = 0;
00463   s->sched = sched;
00464   s->carr_to_code = 1.f / cpc;
00465 
00466   s->A = 1.f - (1.f / (loop_freq * tau));
00467 }
00468 
00480 void comp_tl_update(comp_tl_state_t *s, correlation_t cs[3])
00481 {
00482   float carr_error = costas_discriminator(cs[1].I, cs[1].Q);
00483   s->carr_freq = simple_lf_update(&(s->carr_filt), carr_error);
00484 
00485   float code_error = dll_discriminator(cs);
00486   s->code_filt.y = 0.f;
00487   float code_update = simple_lf_update(&(s->code_filt), -code_error);
00488 
00489   if (s->n > s->sched) {
00490     s->code_freq = s->A * s->code_freq + \
00491                    s->A * code_update + \
00492                    (1.f - s->A)*s->carr_to_code*s->carr_freq;
00493   } else {
00494     s->code_freq += code_update;
00495   }
00496 
00497   s->n++;
00498 }
00499 
00500 
00513 void cn0_est_init(cn0_est_state_t *s, float bw, float cn0_0,
00514                   float cutoff_freq, float loop_freq)
00515 {
00516   s->log_bw = 10.f*log10f(bw);
00517   s->A = cutoff_freq / (loop_freq + cutoff_freq);
00518   s->I_prev_abs = -1.f;
00519   s->nsr = powf(10.f, 0.1f*(s->log_bw - cn0_0));
00520 }
00521 
00575 float cn0_est(cn0_est_state_t *s, float I)
00576 {
00577   float P_n, P_s;
00578 
00579   if (s->I_prev_abs < 0.f) {
00580     /* This is the first iteration, just update the prev state. */
00581     s->I_prev_abs = fabs(I);
00582   } else {
00583     P_n = fabsf(I) - s->I_prev_abs;
00584     P_n = P_n*P_n;
00585 
00586     P_s = 0.5f*(I*I + s->I_prev_abs*s->I_prev_abs);
00587 
00588     s->I_prev_abs = fabsf(I);
00589 
00590     s->nsr = s->A * (P_n / P_s) + (1.f - s->A) * s->nsr;
00591   }
00592 
00593   return s->log_bw - 10.f*log10f(s->nsr);
00594 }
00595 
00596 void calc_navigation_measurement(u8 n_channels, channel_measurement_t meas[],
00597                                  navigation_measurement_t nav_meas[], double nav_time,
00598                                  ephemeris_t ephemerides[])
00599 {
00600   channel_measurement_t* meas_ptrs[n_channels];
00601   navigation_measurement_t* nav_meas_ptrs[n_channels];
00602   ephemeris_t* ephemerides_ptrs[n_channels];
00603 
00604   for (u8 i=0; i<n_channels; i++) {
00605     meas_ptrs[i] = &meas[i];
00606     nav_meas_ptrs[i] = &nav_meas[i];
00607     ephemerides_ptrs[i] = &ephemerides[meas[i].prn];
00608   }
00609 
00610   calc_navigation_measurement_(n_channels, meas_ptrs, nav_meas_ptrs, nav_time, ephemerides_ptrs);
00611 }
00612 
00613 void calc_navigation_measurement_(u8 n_channels, channel_measurement_t* meas[], navigation_measurement_t* nav_meas[], double nav_time, ephemeris_t* ephemerides[])
00614 {
00615   double TOTs[n_channels];
00616   double min_TOT = DBL_MAX;
00617 
00618   for (u8 i=0; i<n_channels; i++) {
00619     TOTs[i] = 1e-3 * meas[i]->time_of_week_ms;
00620     TOTs[i] += meas[i]->code_phase_chips / 1.023e6;
00621     TOTs[i] += (nav_time - meas[i]->receiver_time) * meas[i]->code_phase_rate / 1.023e6;
00622 
00624     nav_meas[i]->tot.wn = ephemerides[i]->toe.wn;
00625     nav_meas[i]->tot.tow = TOTs[i];
00626 
00627     if (gpsdifftime(nav_meas[i]->tot, ephemerides[i]->toe) > 3*24*3600)
00628       nav_meas[i]->tot.wn -= 1;
00629 
00630     if (TOTs[i] < min_TOT)
00631       min_TOT = TOTs[i];
00632 
00633     nav_meas[i]->raw_doppler = meas[i]->carrier_freq;
00634     nav_meas[i]->snr = meas[i]->snr;
00635     nav_meas[i]->prn = meas[i]->prn;
00636 
00637     nav_meas[i]->carrier_phase = meas[i]->carrier_phase;
00638     nav_meas[i]->carrier_phase += (nav_time - meas[i]->receiver_time) * meas[i]->carrier_freq;
00639 
00640     nav_meas[i]->lock_counter = meas[i]->lock_counter;
00641   }
00642 
00643   double clock_err, clock_rate_err;
00644 
00645   for (u8 i=0; i<n_channels; i++) {
00646     nav_meas[i]->raw_pseudorange = (min_TOT - TOTs[i])*GPS_C + GPS_NOMINAL_RANGE;
00647 
00648     calc_sat_pos(nav_meas[i]->sat_pos, nav_meas[i]->sat_vel, &clock_err, &clock_rate_err, ephemerides[i], nav_meas[i]->tot);
00649 
00650     nav_meas[i]->pseudorange = nav_meas[i]->raw_pseudorange \
00651                                + clock_err*GPS_C;
00652     nav_meas[i]->doppler = nav_meas[i]->raw_doppler + clock_rate_err*GPS_L1_HZ;
00653 
00654     nav_meas[i]->tot.tow -= clock_err;
00655     nav_meas[i]->tot = normalize_gps_time(nav_meas[i]->tot);
00656   }
00657 }
00658 
00662 int nav_meas_cmp(const void *a, const void *b)
00663 {
00664   return (s8)((navigation_measurement_t*)a)->prn
00665        - (s8)((navigation_measurement_t*)b)->prn;
00666 }
00667 
00680 u8 tdcp_doppler(u8 n_new, navigation_measurement_t *m_new,
00681                 u8 n_old, navigation_measurement_t *m_old,
00682                 navigation_measurement_t *m_corrected)
00683 {
00684   /* Sort m_new, m_old should already be sorted. */
00685   qsort(m_new, n_new, sizeof(navigation_measurement_t), nav_meas_cmp);
00686 
00687   u8 i, j, n = 0;
00688 
00689   /* Loop over m_new and m_old and check if a PRN is present in both. */
00690   for (i=0, j=0; i<n_new && j<n_old; i++, j++) {
00691     if (m_new[i].prn < m_old[j].prn)
00692       j--;
00693     else if (m_new[i].prn > m_old[j].prn)
00694       i--;
00695     else {
00696       /* Copy m_new to m_corrected. */
00697       memcpy(&m_corrected[n], &m_new[i], sizeof(navigation_measurement_t));
00698       /* Calculate the Doppler correction between raw and corrected. */
00699       double dopp_corr = m_corrected[n].doppler - m_corrected[n].raw_doppler;
00700       /* Calculate raw Doppler from time difference of carrier phase. */
00701       /* TODO: check that using difference of TOTs here is a valid
00702        * approximation. */
00703       m_corrected[n].raw_doppler = (m_new[i].carrier_phase - m_old[j].carrier_phase)
00704                                     / gpsdifftime(m_new[i].tot, m_old[j].tot);
00705       /* Re-apply the same correction to the raw Doppler to get the corrected Doppler. */
00706       m_corrected[n].doppler = m_corrected[n].raw_doppler + dopp_corr;
00707       n++;
00708     }
00709   }
00710 
00711   return n;
00712 }
00713 


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:15