00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <math.h>
00015 #include <string.h>
00016 #include <stdio.h>
00017
00018 #include "linear_algebra.h"
00019 #include "coord_system.h"
00020
00021 #include "pvt.h"
00022 #include "track.h"
00023
00024 static double vel_solve(double rx_vel[],
00025 const navigation_measurement_t const nav_meas[GPS_NUM_SATS],
00026 const u8 n_used,
00027 const double const G[n_used][4],
00028 const double const X[4][n_used])
00029 {
00030
00031
00032
00033
00034
00035
00036
00037
00038 double tempvX[n_used];
00039 double pdot_pred;
00040
00041 for (u8 j = 0; j < n_used; j++) {
00042
00043
00044
00045
00046 pdot_pred = -vector_dot(3, G[j], nav_meas[j].sat_vel);
00047
00048
00049 tempvX[j] = nav_meas[j].pseudorange_rate - pdot_pred;
00050 }
00051
00052
00053
00054
00055
00056 matrix_multiply(4, n_used, 1, (double *) X, (double *) tempvX, (double *) rx_vel);
00057
00058
00059 return rx_vel[3];
00060 }
00061
00062 void compute_dops(const double const H[4][4],
00063 const double const pos_ecef[3],
00064 dops_t *dops)
00065 {
00066 double H_pos_diag[3];
00067 double H_ned[3];
00068
00069 dops->gdop = dops->pdop = dops->tdop = dops->hdop = dops->vdop = 0;
00070
00071
00072 for (u8 i=0; i<3; i++) {
00073 dops->pdop += H[i][i];
00074
00075
00076
00077 H_pos_diag[i] = H[i][i];
00078 }
00079 dops->pdop = sqrt(dops->pdop);
00080
00081
00082 dops->tdop = sqrt(H[3][3]);
00083
00084
00085 dops->gdop = sqrt(dops->tdop*dops->tdop + dops->pdop*dops->pdop);
00086
00087
00088
00089
00090 wgsecef2ned(H_pos_diag, pos_ecef, H_ned);
00091 dops->vdop = sqrt(H_ned[2]*H_ned[2]);
00092 dops->hdop = sqrt(H_ned[0]*H_ned[0] + H_ned[1]*H_ned[1]);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static double pvt_solve(double rx_state[],
00130 const u8 n_used,
00131 const navigation_measurement_t const nav_meas[n_used],
00132 double H[4][4])
00133 {
00134 double p_pred[n_used];
00135
00136
00137 double omp[n_used];
00138
00139
00140
00141
00142 double G[n_used][4];
00143 double Gtrans[4][n_used];
00144 double GtG[4][4];
00145
00146
00147
00148
00149
00150
00151
00152 double X[4][n_used];
00153
00154 double tempv[3];
00155 double los[3];
00156 double xk_new[3];
00157 double tempd;
00158 double correction[4];
00159
00160 for (u8 j=0; j<4; j++) {
00161 correction[j] = 0.0;
00162 }
00163
00164 for (u8 j = 0; j < n_used; j++) {
00165
00166
00167
00168 vector_subtract(3, rx_state, nav_meas[j].sat_pos, tempv);
00169
00170
00171 double tau = vector_norm(3, tempv) / NAV_C;
00172
00173 double wEtau = NAV_OMEGAE_DOT * tau;
00174
00175
00176
00177
00178 double rotm[3][3];
00179 rotm[0][0] = cos(wEtau);
00180 rotm[0][1] = sin(wEtau);
00181 rotm[0][2] = 0.0;
00182 rotm[1][0] = -sin(wEtau);
00183 rotm[1][1] = cos(wEtau);
00184 rotm[1][2] = 0.0;
00185 rotm[2][0] = 0.0;
00186 rotm[2][1] = 0.0;
00187 rotm[2][2] = 1.0;
00188
00189
00190 matrix_multiply(3, 3, 1, (double *) rotm,
00191 (double *) nav_meas[j].sat_pos,
00192 (double *) xk_new);
00193
00194
00195 vector_subtract(3, xk_new, rx_state, los);
00196
00197
00198 p_pred[j] = vector_norm(3, los);
00199
00200
00201
00202
00203
00204 omp[j] = nav_meas[j].pseudorange - p_pred[j];
00205
00206
00207
00208
00209
00210 for (u8 i=0; i<3; i++) {
00211 G[j][i] = -los[i] / p_pred[j];
00212 }
00213
00214
00215 G[j][3] = 1;
00216
00217 }
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 matrix_transpose(n_used, 4, (double *) G, (double *) Gtrans);
00229
00230 matrix_multiply(4, n_used, 4, (double *) Gtrans, (double *) G, (double *) GtG);
00231
00232 matrix_inverse(4, (const double *) GtG, (double *) H);
00233
00234 matrix_multiply(4, 4, n_used, (double *) H, (double *) Gtrans, (double *) X);
00235
00236 matrix_multiply(4, n_used, 1, (double *) X, (double *) omp, (double *) correction);
00237
00238
00239 for (u8 i=0; i<3; i++) {
00240 rx_state[i] += correction[i];
00241 }
00242
00243
00244 for (u8 i=3; i<4; i++) {
00245 rx_state[i] = correction[i];
00246 }
00247
00248
00249
00250
00251 tempd = vector_norm(3, correction);
00252 if(tempd > 0.001) {
00253
00254
00255
00256 return -tempd;
00257 }
00258
00259
00260
00261
00262 vel_solve(&rx_state[4], nav_meas, n_used, (const double (*)[4]) G, (const double (*)[n_used]) X);
00263
00264 return tempd;
00265 }
00266
00267 u8 filter_solution(gnss_solution* soln, dops_t* dops)
00268 {
00269 if (dops->pdop > 50.0)
00270
00271 return 1;
00272
00273 if (soln->pos_llh[2] < -1e3 || soln->pos_llh[2] > 1e8)
00274
00275 return 2;
00276
00277
00278
00279
00280
00281 if (soln->pos_llh[2] >= 0.3048*60000 &&
00282 vector_norm(3, soln->vel_ecef) >= 0.514444444*1000)
00283
00284 return 3;
00285
00286 return 0;
00287 }
00288
00289 u8 calc_PVT(const u8 n_used,
00290 const navigation_measurement_t const nav_meas[n_used],
00291 gnss_solution *soln,
00292 dops_t *dops)
00293 {
00294
00295
00296
00297
00298
00299
00300
00301 static double rx_state[8];
00302
00303 double H[4][4];
00304
00305 soln->valid = 0;
00306
00307 soln->n_used = n_used;
00308
00309
00310 for(u8 i=4; i<8; i++) {
00311 rx_state[i] = 0;
00312 }
00313
00314 double update;
00315 u8 iters;
00316
00317 for (iters=0; iters<PVT_MAX_ITERATIONS; iters++) {
00318 if ((update = pvt_solve(rx_state, n_used, nav_meas, H)) > 0) {
00319 break;
00320 }
00321 }
00322
00323
00324 compute_dops((const double(*)[4])H, rx_state, dops);
00325 soln->err_cov[6] = dops->gdop;
00326
00327
00328
00329
00330 soln->err_cov[0] = H[0][0];
00331 soln->err_cov[1] = H[0][1];
00332 soln->err_cov[2] = H[0][2];
00333 soln->err_cov[3] = H[1][1];
00334 soln->err_cov[4] = H[1][2];
00335 soln->err_cov[5] = H[2][2];
00336
00337 if (iters >= PVT_MAX_ITERATIONS) {
00338 printf("Position solution not available after %d iterations, giving up.\n", iters);
00339
00340 rx_state[0] = 0;
00341 rx_state[1] = 0;
00342 rx_state[2] = 0;
00343 return -1;
00344 }
00345
00346
00347 for (u8 i=0; i<3; i++) {
00348 soln->pos_ecef[i] = rx_state[i];
00349 soln->vel_ecef[i] = rx_state[4+i];
00350 }
00351
00352 wgsecef2ned(soln->vel_ecef, soln->pos_ecef, soln->vel_ned);
00353
00354
00355 wgsecef2llh(rx_state, soln->pos_llh);
00356
00357 soln->clock_offset = rx_state[3] / NAV_C;
00358 soln->clock_bias = rx_state[7] / NAV_C;
00359
00360
00361
00362
00363 soln->time = nav_meas[0].tot;
00364 soln->time.tow -= rx_state[3] / NAV_C;
00365 normalize_gps_time(soln->time);
00366
00367 u8 ret;
00368 if ((ret = filter_solution(soln, dops))) {
00369 memset(soln, 0, sizeof(*soln));
00370 memset(dops, 0, sizeof(*dops));
00371
00372 rx_state[0] = 0;
00373 rx_state[1] = 0;
00374 rx_state[2] = 0;
00375 printf("Solution filtered: %d\n", ret);
00376 return -1;
00377 }
00378
00379 soln->valid = 1;
00380 return 0;
00381 }
00382