single_diff.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 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 <stdio.h>
00014 #include <string.h>
00015 
00016 #include "linear_algebra.h"
00017 #include "single_diff.h"
00018 #include "ephemeris.h"
00019 #include "constants.h"
00020 #include "sats_management.h"
00021 
00026 #define GPS_L1_LAMBDA (GPS_C / GPS_L1_HZ)
00027 
00028 u8 propagate(u8 n, double ref_ecef[3],
00029              navigation_measurement_t *m_in_base, gps_time_t *t_base,
00030              navigation_measurement_t *m_in_rover, gps_time_t *t_rover,
00031              navigation_measurement_t *m_out_base)
00032 {
00033   double dt = gpsdifftime(*t_rover, *t_base);
00034   (void)dt;
00035 
00036   double dr_[n];
00037 
00038   for (u8 i=0; i<n; i++) {
00039     m_out_base[i].prn = m_in_base[i].prn;
00040     m_out_base[i].snr = m_in_base[i].snr;
00041     m_out_base[i].lock_time = m_in_base[i].lock_time;
00042 
00043     /* Calculate delta range. */
00044     double dr[3];
00045     vector_subtract(3, m_in_rover[i].sat_pos, m_in_base[i].sat_pos, dr);
00046 
00047     /* Subtract linear term (initial satellite velocity * dt),
00048      * we are going to add back in the linear term derived from the Doppler
00049      * instead. */
00050     /*vector_add_sc(3, dr, m_in_base[i].sat_vel, -dt, dr);*/
00051 
00052     /* Make unit vector to satellite, e. */
00053     double e[3];
00054     vector_subtract(3, m_in_rover[i].sat_pos, ref_ecef, e);
00055     vector_normalize(3, e);
00056 
00057     /* Project onto the line of sight vector. */
00058     dr_[i] = vector_dot(3, dr, e);
00059 
00060     /*printf("# ddr_ = %f\n", dr_[i]);*/
00061 
00062     /* Add back in linear term now using Doppler. */
00063     /*dr_[i] -= m_in_base[i].raw_doppler * dt * GPS_L1_LAMBDA;*/
00064 
00065     /*printf("# dr_dopp = %f\n", -m_in_base[i].raw_doppler * dt * GPS_L1_LAMBDA);*/
00066 
00067     /*printf("# raw dopp = %f\n", m_in_rover[i].raw_doppler);*/
00068     /*printf("# my dopp = %f\n", -vector_dot(3, e, m_in_rover[i].sat_vel) / GPS_L1_LAMBDA);*/
00069     /*printf("# ddopp = %f\n", m_in_rover[i].raw_doppler - vector_dot(3, e, m_in_rover[i].sat_vel) / GPS_L1_LAMBDA);*/
00070     /*printf("[%f, %f],", m_in_base[i].raw_doppler, vector_dot(3, e, m_in_rover[i].sat_vel) / GPS_L1_LAMBDA);*/
00071 
00072     /*printf("# dr_ = %f\n", dr_[i]);*/
00073 
00074     m_out_base[i].raw_pseudorange = m_in_base[i].raw_pseudorange + dr_[i];
00075     m_out_base[i].pseudorange = m_in_base[i].pseudorange;
00076     m_out_base[i].carrier_phase = m_in_base[i].carrier_phase - dr_[i] / GPS_L1_LAMBDA;
00077     m_out_base[i].raw_doppler = m_in_base[i].raw_doppler;
00078     m_out_base[i].doppler = m_in_base[i].doppler;
00079     /*m_in_base[i].carrier_phase -= dr_[i] / GPS_L1_LAMBDA;*/
00080   }
00081   return 0;
00082 }
00083 
00099 u8 single_diff(u8 n_a, navigation_measurement_t *m_a,
00100                u8 n_b, navigation_measurement_t *m_b,
00101                sdiff_t *sds)
00102 {
00103   u8 i, j, n = 0;
00104 
00105   /* Loop over m_a and m_b and check if a PRN is present in both. */
00106   for (i=0, j=0; i<n_a && j<n_b; i++, j++) {
00107     if (m_a[i].prn < m_b[j].prn)
00108       j--;
00109     else if (m_a[i].prn > m_b[j].prn)
00110       i--;
00111     else {
00112       sds[n].prn = m_a[i].prn;
00113       sds[n].pseudorange = m_a[i].raw_pseudorange - m_b[j].raw_pseudorange;
00114       sds[n].carrier_phase = m_a[i].carrier_phase - m_b[j].carrier_phase;
00115       sds[n].doppler = m_a[i].raw_doppler - m_b[j].raw_doppler;
00116       sds[n].snr = MIN(m_a[i].snr, m_b[j].snr);
00117 
00118       memcpy(&(sds[n].sat_pos), &(m_a[i].sat_pos), 3*sizeof(double));
00119       memcpy(&(sds[n].sat_vel), &(m_a[i].sat_vel), 3*sizeof(double));
00120 
00121       n++;
00122     }
00123   }
00124 
00125   return n;
00126 }
00127 
00128 int sdiff_search_prn(const void *a, const void *b)
00129 {
00130   return (*(u8*)a - ((sdiff_t *)b)->prn);
00131 }
00132 
00162 u8 make_propagated_sdiffs(u8 n_local, navigation_measurement_t *m_local,
00163                           u8 n_remote, navigation_measurement_t *m_remote,
00164                           double *remote_dists, double remote_pos_ecef[3],
00165                           ephemeris_t *es, gps_time_t t,
00166                           sdiff_t *sds)
00167 {
00168   u8 i, j, n = 0;
00169 
00170   /* Loop over m_a and m_b and check if a PRN is present in both. */
00171   for (i=0, j=0; i<n_local && j<n_remote; i++, j++) {
00172     if (m_local[i].prn < m_remote[j].prn)
00173       j--;
00174     else if (m_local[i].prn > m_remote[j].prn)
00175       i--;
00176     else if (ephemeris_good(es[m_local[i].prn], t)) {
00177       double clock_err;
00178       double clock_rate_err;
00179       double local_sat_pos[3];
00180       double local_sat_vel[3];
00181       calc_sat_pos(&local_sat_pos[0],
00182                    &local_sat_vel[0],
00183                    &clock_err, &clock_rate_err, &es[m_local[i].prn], t);
00184       sds[n].prn = m_local[i].prn;
00185       double dx = local_sat_pos[0] - remote_pos_ecef[0];
00186       double dy = local_sat_pos[1] - remote_pos_ecef[1];
00187       double dz = local_sat_pos[2] - remote_pos_ecef[2];
00188       double new_dist = sqrt( dx * dx + dy * dy + dz * dz);
00189       double dist_diff = new_dist - remote_dists[j];
00190       /* Explanation:
00191        * pseudorange = dist + c
00192        * To update a pseudorange in time:
00193        *  new_pseudorange = new_dist + c
00194        *                  = old_dist + c + (new_dist - old_dist)
00195        *                  = old_pseudorange + (new_dist - old_dist)
00196        *
00197        * So to get the single differenced pseudorange:
00198        *  local_pseudorange - new_remote_pseudorange
00199        *    = local_pseudorange - (old_remote_pseudorange + new_dist - old_dist)
00200        *
00201        * For carrier phase, it's the same thing, but the update has opposite sign. */
00202       sds[n].pseudorange = m_local[i].raw_pseudorange
00203                          - (m_remote[j].raw_pseudorange
00204                             + dist_diff);
00205       sds[n].carrier_phase = m_local[i].carrier_phase
00206                            - (m_remote[j].carrier_phase
00207                               - dist_diff / GPS_L1_LAMBDA);
00208 
00209       /* Doppler is not propagated.
00210        * sds[n].doppler = m_local[i].raw_doppler - m_remote[j].raw_doppler; */
00211       sds[n].snr = MIN(m_local[i].snr, m_remote[j].snr);
00212       memcpy(&(sds[n].sat_pos), &(local_sat_pos[0]), 3*sizeof(double));
00213       memcpy(&(sds[n].sat_vel), &(local_sat_vel[0]), 3*sizeof(double));
00214 
00215       n++;
00216     }
00217   }
00218 
00219   return n;
00220 }
00221 
00222 
00228 void almanacs_to_single_diffs(u8 n, almanac_t *alms, gps_time_t timestamp, sdiff_t *sdiffs)
00229 {
00230   for (u8 i=0; i<n; i++) {
00231     double p[3];
00232     double v[3];
00233     calc_sat_state_almanac(&alms[i], timestamp.tow, timestamp.wn, p, v);
00234     memcpy(sdiffs[i].sat_pos, &p[0], 3 * sizeof(double));
00235     memcpy(sdiffs[i].sat_vel, &v[0], 3 * sizeof(double));
00236     sdiffs[i].prn = alms[i].prn;
00237     if (i==0) {
00238       sdiffs[i].snr = 1;
00239       // printf("ref_prn=%d\n", sdiffs[i].prn);
00240     }
00241     else {
00242       sdiffs[i].snr = 0;
00243     }
00244     // if (sdiffs[i].prn == 16) {
00245     //   sdiffs[i].snr = 2;
00246     // }
00247   }
00248 }
00249 
00250 void double_diff(u8 n, sdiff_t *sds, sdiff_t *dds, u8 ref_idx)
00251 {
00252   for (u8 i=0; i<n; i++) {
00253     dds[i].prn = sds[i].prn;
00254     dds[i].pseudorange = sds[i].pseudorange - sds[ref_idx].pseudorange;
00255     dds[i].carrier_phase = sds[i].carrier_phase - sds[ref_idx].carrier_phase;
00256     dds[i].doppler = sds[i].doppler - sds[ref_idx].doppler;
00257     dds[i].snr = MIN(sds[i].snr, sds[ref_idx].snr);
00258 
00259     memcpy(&(dds[i].sat_pos), &(sds[i].sat_pos), 3*sizeof(double));
00260     memcpy(&(dds[i].sat_vel), &(sds[i].sat_vel), 3*sizeof(double));
00261   }
00262 }
00263 
00264 s8 copy_sdiffs_put_ref_first(u8 ref_prn, u8 num_sdiffs, sdiff_t *sdiffs, sdiff_t *sdiffs_with_ref_first)
00265 {
00266   s8 not_found = -1;
00267   u8 j = 1;
00268   for (u8 i=0; i<num_sdiffs; i++) {
00269     if (sdiffs[i].prn == ref_prn) {
00270       memcpy(sdiffs_with_ref_first, &sdiffs[i], sizeof(sdiff_t));
00271       not_found = 0;
00272     }
00273     else {
00274       if (j == num_sdiffs) {
00275         return not_found; //note: not_found should always be -1 if it reaches this point. if anyone thinks "return -1" is more clear, go ahead and change it.
00276       }
00277       memcpy(&sdiffs_with_ref_first[j], &sdiffs[i], sizeof(sdiff_t));
00278       j++;
00279     }
00280   }
00281   return not_found;
00282 }
00283 
00284 bool _contains_prn(u8 len, u8 *prns, u8 prn)
00285 {
00286   for (u8 i = 0; i < len; i++) {
00287     if (prns[i] == prn) {
00288       return true;
00289     }
00290   }
00291   return false;
00292 }
00293 
00294 u8 filter_sdiffs(u8 num_sdiffs, sdiff_t *sdiffs, u8 num_sats_to_drop, u8 *sats_to_drop)
00295 {
00296   u8 new_num_sdiffs = 0;
00297   for (u8 i = 0; i < num_sdiffs; i++) {
00298     if (!_contains_prn(num_sats_to_drop, sats_to_drop, sdiffs[i].prn)) {
00299       if (new_num_sdiffs != i) {
00300         memcpy(&sdiffs[new_num_sdiffs], &sdiffs[i], sizeof(sdiff_t));
00301       }
00302       new_num_sdiffs++;
00303     }
00304   }
00305   return new_num_sdiffs;
00306 }
00307 


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