ephemeris.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 Swift Navigation Inc.
00003  * Contact: Henry Hallam <henry@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 "linear_algebra.h"
00014 #include "ephemeris.h"
00015 #include <math.h>
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 
00019 #define NAV_OMEGAE_DOT 7.2921151467e-005
00020 #define NAV_GM 3.986005e14
00021 
00022 int calc_sat_pos(double pos[3], double vel[3],
00023              double *clock_err, double *clock_rate_err,
00024              const ephemeris_t *ephemeris,
00025              gps_time_t tot)
00026 {
00027   /****************************************************************************
00028    * Calculate satellite position, velocity and clock offset from ephemeris
00029    * Taken from IS-GPS-200D, Section 20.3.3.3.3.1 and Table 20-IV
00030    *
00031    * Usage: unsigned int ProcessEphemeris(unsigned int week, double secs,
00032    *                              unsigned int sv, nav_info_t *Eph)
00033    *  week: GPS week number
00034    *  sec: GPS seconds of the week of time of transmission
00035    *  sv: Satellite vehicle number
00036    *    Eph: Ephemeris data structure located within channel structure
00037    ****************************************************************************/
00038 
00039   double tempd1 = 0, tempd2, tempd3;
00040   double tdiff;
00041   double a;     // semi major axis
00042   double ma, ma_dot;    // mean anomoly and first derivative (mean motion)
00043   double ea, ea_dot, ea_old;  // eccentric anomoly, first deriv, iteration var
00044   double einstein;    // relativistic correction
00045   double al, al_dot;    // argument of lattitude and first derivative
00046   double cal, cal_dot;    // corrected argument of lattitude and first deriv
00047   double r, r_dot;    // radius and first derivative
00048   double inc, inc_dot;    // inclination and first derivative
00049   double x, x_dot, y, y_dot;  // position in orbital plan and first derivatives
00050   double om, om_dot;    // omega and first derivatives
00051 
00052 
00053   // Satellite clock terms
00054   // Seconds from clock data reference time (toc)
00055   tdiff = gpsdifftime(tot, ephemeris->toc);
00056 
00057   *clock_err = ephemeris->af0 + tdiff * (ephemeris->af1 + tdiff * ephemeris->af2) - ephemeris->tgd;
00058   *clock_rate_err = ephemeris->af1 + 2.0 * tdiff * ephemeris->af2;
00059 
00060   // Seconds from the time from ephemeris reference epoch (toe)
00061   tdiff = gpsdifftime(tot, ephemeris->toe);
00062 
00063   // If tdiff is too large our ephemeris isn't valid, maybe we want to wait until we get a
00064   // new one? At least let's warn the user.
00065   // TODO: this doesn't exclude ephemerides older than a week so could be made better.
00066   if (fabs(tdiff) > 4*3600)
00067     printf(" WARNING: using ephemeris older (or newer!) than 4 hours.\n");
00068 
00069   // Calculate position per IS-GPS-200D p 97 Table 20-IV
00070   a = ephemeris->sqrta * ephemeris->sqrta;  // [m] Semi-major axis
00071   ma_dot = sqrt (NAV_GM / (a * a * a)) + ephemeris->dn; // [rad/sec] Corrected mean motion
00072   ma = ephemeris->m0 + ma_dot * tdiff;  // [rad] Corrected mean anomaly
00073 
00074   // Iteratively solve for the Eccentric Anomaly (from Keith Alter and David Johnston)
00075   ea = ma;      // Starting value for E
00076   double ecc = ephemeris->ecc;
00077   u32 count = 0;
00078 
00079   /* TODO: Implement convergence test using integer difference of doubles,
00080    * http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm */
00081   do {
00082     ea_old = ea;
00083     tempd1 = 1.0 - ecc * cos (ea_old);
00084     ea = ea + (ma - ea_old + ecc * sin (ea_old)) / tempd1;
00085     count++;
00086     if (count > 5)
00087       break;
00088   } while (fabs (ea - ea_old) > 1.0E-14);
00089   ea_dot = ma_dot / tempd1;
00090 
00091   // Relativistic correction term
00092   einstein = -4.442807633E-10 * ecc * ephemeris->sqrta * sin (ea);
00093 
00094   // Begin calc for True Anomaly and Argument of Latitude
00095   tempd2 = sqrt (1.0 - ecc * ecc);
00096   al = atan2 (tempd2 * sin (ea), cos (ea) - ecc) + ephemeris->w; // [rad] Argument of Latitude = True Anomaly + Argument of Perigee
00097   al_dot = tempd2 * ea_dot / tempd1;
00098 
00099   // Calculate corrected argument of latitude based on position
00100   cal = al + ephemeris->cus * sin (2.0 * al) + ephemeris->cuc * cos (2.0 * al);
00101   cal_dot =
00102     al_dot * (1.0 +
00103         2.0 * (ephemeris->cus * cos (2.0 * al) -
00104          ephemeris->cuc * sin (2.0 * al)));
00105 
00106   // Calculate corrected radius based on argument of latitude
00107   r =
00108     a * tempd1 + ephemeris->crc * cos (2.0 * al) +
00109     ephemeris->crs * sin (2.0 * al);
00110   r_dot =
00111     a * ecc * sin (ea) * ea_dot +
00112     2.0 * al_dot * (ephemeris->crs * cos (2.0 * al) -
00113         ephemeris->crc * sin (2.0 * al));
00114 
00115   // Calculate inclination based on argument of latitude
00116   inc =
00117     ephemeris->inc + ephemeris->inc_dot * tdiff +
00118     ephemeris->cic * cos (2.0 * al) + ephemeris->cis * sin (2.0 * al);
00119   inc_dot =
00120     ephemeris->inc_dot + 2.0 * al_dot * (ephemeris->cis * cos (2.0 * al) -
00121            ephemeris->cic * sin (2.0 * al));
00122 
00123   // Calculate position and velocity in orbital plane
00124   x = r * cos (cal);
00125   y = r * sin (cal);
00126   x_dot = r_dot * cos (cal) - y * cal_dot;
00127   y_dot = r_dot * sin (cal) + x * cal_dot;
00128 
00129   // Corrected longitude of ascenting node
00130   om_dot = ephemeris->omegadot - NAV_OMEGAE_DOT;
00131   om = ephemeris->omega0 + tdiff * om_dot - NAV_OMEGAE_DOT * ephemeris->toe.tow;
00132 
00133   // Compute the satellite's position in Earth-Centered Earth-Fixed coordiates
00134   pos[0] = x * cos (om) - y * cos (inc) * sin (om);
00135   pos[1] = x * sin (om) + y * cos (inc) * cos (om);
00136   pos[2] = y * sin (inc);
00137 
00138   tempd3 = y_dot * cos (inc) - y * sin (inc) * inc_dot;
00139 
00140   // Compute the satellite's velocity in Earth-Centered Earth-Fixed coordiates
00141   vel[0] = -om_dot * pos[1] + x_dot * cos (om) - tempd3 * sin (om);
00142   vel[1] = om_dot * pos[0] + x_dot * sin (om) + tempd3 * cos (om);
00143   vel[2] = y * cos (inc) * inc_dot + y_dot * sin (inc);
00144 
00145   *clock_err += einstein;
00146 
00147   return 0;
00148 }
00149 
00150 double predict_range(double rx_pos[3],
00151                      gps_time_t tot,
00152                      ephemeris_t *ephemeris)
00153 {
00154   double sat_pos[3];
00155   double sat_vel[3];
00156   double temp[3];
00157   double clock_err, clock_rate_err;
00158 
00159   calc_sat_pos(sat_pos, sat_vel, &clock_err, &clock_rate_err, ephemeris, tot);
00160 
00161   vector_subtract(3, sat_pos, rx_pos, temp); // temp = sat_pos - rx_pos
00162   return vector_norm(3, temp);
00163 }
00164 
00174 u8 ephemeris_good(ephemeris_t eph, gps_time_t t)
00175 {
00176 
00177   /* Seconds from the time from ephemeris reference epoch (toe) */
00178   double tdiff = gpsdifftime(t, eph.toe);
00179 
00180   /* \TODO: this doesn't exclude ephemerides older than a week so could be made better. */
00181   return (eph.valid && fabs(tdiff) < 4*3600);
00182 }


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:50