00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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
00107 float omega_n = 8.f*bw*zeta / (4.f*zeta*zeta + 1.f);
00108
00109
00110
00111
00112
00113
00114
00115
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
00143
00144
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;
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);
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
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
00685 qsort(m_new, n_new, sizeof(navigation_measurement_t), nav_meas_cmp);
00686
00687 u8 i, j, n = 0;
00688
00689
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
00697 memcpy(&m_corrected[n], &m_new[i], sizeof(navigation_measurement_t));
00698
00699 double dopp_corr = m_corrected[n].doppler - m_corrected[n].raw_doppler;
00700
00701
00702
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
00706 m_corrected[n].doppler = m_corrected[n].raw_doppler + dopp_corr;
00707 n++;
00708 }
00709 }
00710
00711 return n;
00712 }
00713