Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <math.h>
00014
00015 #include "constants.h"
00016 #include "linear_algebra.h"
00017 #include "coord_system.h"
00018 #include "almanac.h"
00019
00039 void calc_sat_state_almanac(almanac_t* alm, double t, s16 week,
00040 double pos[3], double vel[3])
00041 {
00042
00043 double dt = t - alm->toa;
00044
00045 if (week < 0) {
00046
00047
00048
00049 if (dt > 302400)
00050 dt -= 604800;
00051 else if (dt < -302400)
00052 dt += 604800;
00053 } else {
00054
00055 s32 dweeks = week - alm->week;
00056 dt += dweeks * 604800;
00057 }
00058
00059
00060
00061
00062 double ma_dot = sqrt (GPS_GM / (alm->a * alm->a * alm->a));
00063
00064 double ma = alm->ma + ma_dot * dt;
00065
00066
00067
00068 double ea = ma;
00069 double ea_old;
00070 double temp;
00071 double ecc = alm->ecc;
00072 u32 count = 0;
00073
00074
00075
00076 do {
00077 ea_old = ea;
00078 temp = 1.0 - ecc * cos(ea_old);
00079 ea = ea + (ma - ea_old + ecc * sin(ea_old)) / temp;
00080 count++;
00081 if (count > 5)
00082 break;
00083 } while (fabs(ea - ea_old) > 1.0e-14);
00084
00085 double ea_dot = ma_dot / temp;
00086
00087
00088 double temp2 = sqrt(1.0 - ecc * ecc);
00089
00090 double al = atan2(temp2 * sin(ea), cos(ea) - ecc) + alm->argp;
00091 double al_dot = temp2 * ea_dot / temp;
00092
00093
00094 double r = alm->a * temp;
00095 double r_dot = alm->a * ecc * sin(ea) * ea_dot;
00096
00097
00098 double x = r * cos(al);
00099 double y = r * sin(al);
00100 double x_dot = r_dot * cos(al) - y * al_dot;
00101 double y_dot = r_dot * sin(al) + x * al_dot;
00102
00103
00104 double om_dot = alm->rora - GPS_OMEGAE_DOT;
00105 double om = alm->raaw + dt * om_dot - GPS_OMEGAE_DOT * alm->toa;
00106
00107
00108
00109 pos[0] = x * cos(om) - y * cos(alm->inc) * sin(om);
00110 pos[1] = x * sin(om) + y * cos(alm->inc) * cos(om);
00111 pos[2] = y * sin(alm->inc);
00112
00113
00114
00115 if (vel) {
00116 temp = y_dot * cos(alm->inc);
00117 vel[0] = -om_dot * pos[1] + x_dot * cos(om) - temp * sin(om);
00118 vel[1] = om_dot * pos[0] + x_dot * sin(om) + temp * cos(om);
00119 vel[2] = y_dot * sin(alm->inc);
00120 }
00121
00122 }
00123
00137 void calc_sat_az_el_almanac(almanac_t* alm, double t, s16 week,
00138 double ref[3], double* az, double* el)
00139 {
00140 double sat_pos[3];
00141 calc_sat_state_almanac(alm, t, week, sat_pos, 0);
00142 wgsecef2azel(sat_pos, ref, az, el);
00143 }
00144
00157 double calc_sat_doppler_almanac(almanac_t* alm, double t, s16 week,
00158 double ref[3])
00159 {
00160 double sat_pos[3];
00161 double sat_vel[3];
00162 double vec_ref_sat[3];
00163
00164 calc_sat_state_almanac(alm, t, week, sat_pos, sat_vel);
00165
00166
00167 vector_subtract(3, sat_pos, ref, vec_ref_sat);
00168
00169
00170
00171 double radial_velocity = vector_dot(3, vec_ref_sat, sat_vel) / \
00172 vector_norm(3, vec_ref_sat);
00173
00174
00175 return GPS_L1_HZ * radial_velocity / GPS_C;
00176 }
00177