00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <math.h>
00039 #include <memory.h>
00040 #include <list>
00041
00042 #include "GNSS_Estimator.h"
00043 #include "GNSS_RxData.h"
00044 #include "constants.h"
00045 #include "geodesy.h"
00046 #include "gps.h"
00047 #include "ionosphere.h"
00048 #include "navigation.h"
00049 #include "troposphere.h"
00050 #include "time_conversion.h"
00051
00052 #define DEBUG_THE_ESTIMATOR
00053 #define GNSS_CYCLESLIP_THREADHOLD 1.5
00054
00055 using namespace std;
00056
00057
00058 namespace GNSS
00059 {
00060
00061
00062
00063
00064
00065 #define GNSS_CHISQUARE_00_5 { \
00066 0.000, 7.879, 10.597, 12.838, 14.860, 16.750, 18.548, 20.278, 21.955, 23.589, \
00067 25.188, 26.757, 28.300, 29.819, 31.319, 32.801, 34.267, 35.718, 37.156, 38.582, \
00068 39.997, 41.401, 42.796, 44.181, 45.558, 46.928, 48.290, 49.645, 50.993, 52.336, 53.672 }
00069
00070
00071 GNSS_Estimator::GNSS_Estimator()
00072 : m_debug(NULL)
00073 {
00074 }
00075
00076
00077 GNSS_Estimator::~GNSS_Estimator()
00078 {
00079 if( m_debug )
00080 {
00081 fclose(m_debug);
00082 }
00083 }
00084
00085
00086 bool GNSS_Estimator::PerformLeastSquares_8StatePVT(
00087 GNSS_RxData *rxData,
00088 GNSS_RxData *rxBaseData,
00089 bool &wasPositionComputed,
00090 bool &wasVelocityComputed
00091 )
00092 {
00093 unsigned i = 0;
00094 unsigned j = 0;
00095
00096 unsigned iter = 0;
00097 unsigned n = 0;
00098 unsigned nrValidEph = 0;
00099 unsigned nrP = 0;
00100 unsigned nrP_base = 0;
00101 unsigned nrD = 0;
00102
00103 unsigned nrDifferentialPsr = 0;
00104 unsigned nrDifferentialDoppler = 0;
00105
00106
00107
00108 double dtmp1 = 0;
00109 double lat = 0;
00110 double lon = 0;
00111 double hgt = 0;
00112 double clk = 0;
00113 double clkdrift = 0;
00114 double vn = 0;
00115 double ve = 0;
00116 double vup = 0;
00117 double M = 0;
00118 double N = 0;
00119
00120 Matrix dx_p(4);
00121 Matrix dx_v(4);
00122 Matrix P_p(4,4);
00123 Matrix P_v(4,4);
00124 Matrix H_p;
00125 Matrix Ht_p;
00126 Matrix HtW_p;
00127 Matrix H_v;
00128 Matrix Ht_v;
00129 Matrix HtW_v;
00130 Matrix W_p;
00131 Matrix R_p;
00132 Matrix W_v;
00133 Matrix R_v;
00134 Matrix w_p;
00135 Matrix w_v;
00136 Matrix r_p;
00137 Matrix r_v;
00138
00139 double avf_p = 0;
00140
00141
00142 bool isGlobalTestPassed_p = false;
00143
00144
00145 bool hasRejectionOccurred_p = false;
00146
00147
00148 unsigned char indexOfRejected = 0;
00149
00150 bool result = false;
00151
00152 if( rxData == NULL )
00153 return false;
00154
00155
00156 rxData->m_prev_pvt = rxData->m_pvt;
00157
00158 lat = rxData->m_pvt.latitude;
00159 lon = rxData->m_pvt.longitude;
00160 hgt = rxData->m_pvt.height;
00161 clk = rxData->m_pvt.clockOffset;
00162
00163 vn = rxData->m_pvt.vn;
00164 ve = rxData->m_pvt.ve;
00165 vup = rxData->m_pvt.vup;
00166 clkdrift = rxData->m_pvt.clockDrift;
00167
00168 wasPositionComputed = false;
00169 wasVelocityComputed = false;
00170
00171
00172 n = rxData->m_nrGPSL1Obs;
00173 if( rxData->m_pvt.isPositionConstrained )
00174 {
00175 n += 3;
00176 }
00177 else if( rxData->m_pvt.isHeightConstrained )
00178 {
00179 n += 1;
00180 }
00181 if( n < 4 )
00182 {
00183 return true;
00184 }
00185
00186
00187 result = UpdateTime( *rxData );
00188 if( !result )
00189 return false;
00190 if( rxBaseData != NULL )
00191 {
00192 result = UpdateTime( *rxBaseData );
00193 if( !result )
00194 return false;
00195 }
00196
00197
00198
00199
00200 result = DetermineSatellitePVT_GPSL1( rxData, rxBaseData, nrValidEph );
00201 if( !result )
00202 return false;
00203
00204 result = DetermineAtmosphericCorrections_GPSL1( *rxData );
00205 if( !result )
00206 return false;
00207 if( rxBaseData != NULL )
00208 {
00209 result = DetermineAtmosphericCorrections_GPSL1( *rxBaseData );
00210 if( !result )
00211 return false;
00212 }
00213
00214
00215 n = nrValidEph;
00216 if( rxData->m_pvt.isPositionConstrained )
00217 {
00218 n += 3;
00219 }
00220 else if( rxData->m_pvt.isHeightConstrained )
00221 {
00222 n += 1;
00223 }
00224 if( n < 4 )
00225 {
00226 return true;
00227 }
00228
00229
00230
00231 for( iter = 0; iter < 7; iter++ )
00232 {
00233 if( !DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxData, nrP ) )
00234 return false;
00235
00236
00237 n = nrP;
00238 if( rxData->m_pvt.isPositionConstrained )
00239 {
00240 n += 3;
00241 }
00242 else if( rxData->m_pvt.isHeightConstrained )
00243 {
00244 n += 1;
00245 }
00246 if( n < 4 )
00247 {
00248 return true;
00249 }
00250
00251 if( rxBaseData != NULL )
00252 {
00253 if( !DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxBaseData, nrP_base ) )
00254 return false;
00255
00256 result = DetermineBetweenReceiverDifferentialIndex(
00257 rxData,
00258 rxBaseData,
00259 true
00260 );
00261 if( !result )
00262 return false;
00263
00264 nrDifferentialPsr = 0;
00265 for( i = 0; i < rxData->m_nrValidObs; i++ )
00266 {
00267 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
00268 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
00269 rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
00270 {
00271 nrDifferentialPsr++;
00272 }
00273 }
00274
00275 nrP = nrDifferentialPsr;
00276 n = nrP;
00277 if( rxData->m_pvt.isPositionConstrained )
00278 {
00279 n += 3;
00280 }
00281 else if( rxData->m_pvt.isHeightConstrained )
00282 {
00283 n += 1;
00284 }
00285 if( n < 4 )
00286 {
00287 return true;
00288 }
00289 }
00290
00291 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
00292 *rxData,
00293 n,
00294 H_p );
00295 if( !result )
00296 return false;
00297
00298 result = DetermineMeasurementWeightMatrixForThePositionSolution_GPSL1(
00299 *rxData,
00300 n,
00301 W_p );
00302 if( !result )
00303 return false;
00304
00305 result = DetermineMeasurementVarianceCovarianceMatrixForThePositionSolution_GPSL1(
00306 *rxData,
00307 n,
00308 R_p );
00309 if( !result )
00310 return false;
00311
00312 result = DeterminePseudorangeMisclosures_GPSL1(
00313 rxData,
00314 rxBaseData,
00315 n,
00316 w_p );
00317 if( !result )
00318 return false;
00319
00320
00321 Ht_p = H_p;
00322 if( !Ht_p.Inplace_Transpose() )
00323 return false;
00324
00325
00326 if( !HtW_p.Multiply( Ht_p, W_p ) )
00327 return false;
00328
00329
00330 if( !P_p.Multiply( HtW_p, H_p ) )
00331 return false;
00332 if( !P_p.Inplace_Invert() )
00333 return false;
00334
00335
00336 if( !dx_p.Multiply( P_p, HtW_p ) )
00337 return false;
00338 if( !dx_p.Inplace_PostMultiply( w_p ) )
00339 return false;
00340
00341
00342
00343 hgt += dx_p[2];
00344 clk += dx_p[3];
00345
00346
00347 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
00348 GEODESY_REFERENCE_ELLIPSE_WGS84,
00349 rxData->m_pvt.latitude,
00350 &N );
00351 GEODESY_ComputeMeridianRadiusOfCurvature(
00352 GEODESY_REFERENCE_ELLIPSE_WGS84,
00353 rxData->m_pvt.latitude,
00354 &M );
00355
00356 lat += dx_p[0] / ( M + hgt );
00357 lon += dx_p[1] / (( N + hgt )*cos(lat));
00358
00359 result = rxData->UpdatePositionAndRxClock(
00360 lat,
00361 lon,
00362 hgt,
00363 clk,
00364 sqrt(P_p[0][0]),
00365 sqrt(P_p[1][1]),
00366 sqrt(P_p[2][2]),
00367 sqrt(P_p[3][3])
00368 );
00369 if( !result )
00370 return false;
00371
00372 dtmp1 = fabs(dx_p[0]) + fabs(dx_p[1]) + fabs(dx_p[2]) + fabs(dx_p[3]);
00373 if( dtmp1 < 0.0001 )
00374 {
00375 if( 0 )
00376 {
00377
00378 result = PerformGlobalTestAndTestForMeasurementFaults(
00379 *rxData,
00380 true,
00381 H_p,
00382 Ht_p,
00383 W_p,
00384 R_p,
00385 w_p,
00386 P_p,
00387 n,
00388 4,
00389 avf_p,
00390 isGlobalTestPassed_p,
00391 hasRejectionOccurred_p,
00392 indexOfRejected
00393 );
00394 if( !result )
00395 return false;
00396
00397 if( hasRejectionOccurred_p )
00398 {
00399 hasRejectionOccurred_p = false;
00400 j = 0;
00401 continue;
00402 }
00403 else
00404 {
00405
00406 break;
00407 }
00408 }
00409 else
00410 {
00411
00412 break;
00413 }
00414
00415 }
00416 }
00417 wasPositionComputed = true;
00418
00419
00420
00421 Matrix Q;
00422 Q = H_p;
00423 Q.Inplace_Transpose();
00424 Q.Inplace_PostMultiply( H_p );
00425 if( !Q.Inplace_Invert() )
00426 return false;
00427
00428 rxData->m_pvt.dop.ndop = static_cast<float>( sqrt( Q[0][0] ) );
00429 rxData->m_pvt.dop.edop = static_cast<float>( sqrt( Q[1][1] ) );
00430 rxData->m_pvt.dop.vdop = static_cast<float>( sqrt( Q[2][2] ) );
00431 rxData->m_pvt.dop.tdop = static_cast<float>( sqrt( Q[3][3] ) );
00432 rxData->m_pvt.dop.hdop = rxData->m_pvt.dop.ndop * rxData->m_pvt.dop.ndop + rxData->m_pvt.dop.edop * rxData->m_pvt.dop.edop;
00433 rxData->m_pvt.dop.pdop = rxData->m_pvt.dop.hdop + rxData->m_pvt.dop.vdop * rxData->m_pvt.dop.vdop;
00434 rxData->m_pvt.dop.gdop = rxData->m_pvt.dop.pdop + rxData->m_pvt.dop.tdop * rxData->m_pvt.dop.tdop;
00435 rxData->m_pvt.dop.hdop = sqrt(rxData->m_pvt.dop.hdop);
00436 rxData->m_pvt.dop.pdop = sqrt(rxData->m_pvt.dop.pdop);
00437 rxData->m_pvt.dop.gdop = sqrt(rxData->m_pvt.dop.gdop);
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 for( iter = 0; iter < 7; iter++ )
00448 {
00449 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1(
00450 *rxData,
00451 nrD );
00452 if( !result )
00453 return false;
00454
00455
00456 n = nrD;
00457 if( rxData->m_pvt.isPositionConstrained )
00458 {
00459 n += 3;
00460 }
00461 else if( rxData->m_pvt.isHeightConstrained )
00462 {
00463 n += 1;
00464 }
00465 if( n < 4 )
00466 {
00467 return true;
00468 }
00469
00470
00471 if( rxBaseData != NULL )
00472 {
00473 if( !DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxBaseData, nrP_base ) )
00474 return false;
00475
00476 result = DetermineBetweenReceiverDifferentialIndex(
00477 rxData,
00478 rxBaseData,
00479 true
00480 );
00481 if( !result )
00482 return false;
00483
00484 nrDifferentialDoppler = 0;
00485 for( i = 0; i < rxData->m_nrValidObs; i++ )
00486 {
00487 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
00488 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
00489 rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
00490 {
00491 nrDifferentialDoppler++;
00492 }
00493 }
00494
00495
00496 nrD = nrDifferentialDoppler;
00497 n = nrD;
00498 if( rxData->m_pvt.isPositionConstrained )
00499 {
00500 n += 3;
00501 }
00502 else if( rxData->m_pvt.isHeightConstrained )
00503 {
00504 n += 1;
00505 }
00506 if( n < 4 )
00507 {
00508 return true;
00509 }
00510 }
00511
00512
00513
00514 for( i = 0; i < rxData->m_nrValidObs; i++ )
00515 {
00516 if( rxData->m_ObsArray[i].flags.isActive )
00517 {
00518 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
00519 {
00520 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
00521 {
00522 GPS_ComputeUserToSatelliteRangeAndRangeRate(
00523 rxData->m_pvt.x,
00524 rxData->m_pvt.y,
00525 rxData->m_pvt.z,
00526 rxData->m_pvt.vx,
00527 rxData->m_pvt.vy,
00528 rxData->m_pvt.vz,
00529 rxData->m_ObsArray[i].satellite.x,
00530 rxData->m_ObsArray[i].satellite.y,
00531 rxData->m_ObsArray[i].satellite.z,
00532 rxData->m_ObsArray[i].satellite.vx,
00533 rxData->m_ObsArray[i].satellite.vy,
00534 rxData->m_ObsArray[i].satellite.vz,
00535 &rxData->m_ObsArray[i].range,
00536 &rxData->m_ObsArray[i].rangerate
00537 );
00538 }
00539 }
00540 }
00541 }
00542
00543 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
00544 *rxData,
00545 n,
00546 H_v );
00547 if( !result )
00548 return false;
00549
00550 result = DetermineMeasurementWeightMatrixForTheVelocitySolution_GPSL1(
00551 *rxData,
00552 n,
00553 W_v );
00554 if( !result )
00555 return false;
00556
00557 result = DetermineMeasurementVarianceCovarianceMatrixForTheVelocitySolution_GPSL1(
00558 *rxData,
00559 n,
00560 R_v );
00561 if( !result )
00562 return false;
00563
00564 result = DetermineDopplerMisclosures_GPSL1(
00565 rxData,
00566 rxBaseData,
00567 n,
00568 w_v );
00569 if( !result )
00570 return false;
00571
00572
00573 Ht_v = H_v;
00574 if( !Ht_v.Inplace_Transpose() )
00575 return false;
00576
00577
00578 if( !HtW_v.Multiply( Ht_v, W_v ) )
00579 return false;
00580
00581
00582 if( !P_v.Multiply( HtW_v, H_v ) )
00583 return false;
00584 if( !P_v.Inplace_Invert() )
00585 return false;
00586
00587
00588 if( !dx_v.Multiply( P_v, HtW_v ) )
00589 return false;
00590 if( !dx_v.Inplace_PostMultiply( w_v ) )
00591 return false;
00592
00593
00594 vn += dx_v[0];
00595 ve += dx_v[1];
00596 vup += dx_v[2];
00597 clkdrift += dx_v[3];
00598
00599 result = rxData->UpdateVelocityAndClockDrift(
00600 vn,
00601 ve,
00602 vup,
00603 clkdrift,
00604 P_v[0][0],
00605 P_v[1][1],
00606 P_v[2][2],
00607 P_v[3][3] );
00608 if( !result )
00609 return false;
00610
00611 dtmp1 = fabs(dx_v[0]) + fabs(dx_v[1]) + fabs(dx_v[2]) + fabs(dx_v[3]);
00612 if( dtmp1 < 1.0e-10 )
00613 break;
00614 }
00615 wasVelocityComputed = true;
00616
00617 return true;
00618 }
00619
00620
00621 bool GNSS_Estimator::UpdateTime(
00622 GNSS_RxData &rxData
00623 )
00624 {
00625 TIMECONV_GetUTCTimeFromGPSTime(
00626 rxData.m_pvt.time.gps_week,
00627 rxData.m_pvt.time.gps_tow,
00628 &rxData.m_pvt.time.utc_year,
00629 &rxData.m_pvt.time.utc_month,
00630 &rxData.m_pvt.time.utc_day,
00631 &rxData.m_pvt.time.utc_hour,
00632 &rxData.m_pvt.time.utc_minute,
00633 &rxData.m_pvt.time.utc_seconds
00634 );
00635
00636 TIMECONV_GetDayOfYear(
00637 rxData.m_pvt.time.utc_year,
00638 rxData.m_pvt.time.utc_month,
00639 rxData.m_pvt.time.utc_day,
00640 &rxData.m_pvt.time.day_of_year );
00641
00642 return true;
00643 }
00644
00645
00646 bool GNSS_Estimator::DetermineSatellitePVT_GPSL1(
00647 GNSS_RxData *rxData,
00648 GNSS_RxData *rxBaseData,
00649 unsigned &nrValidEph
00650 )
00651 {
00652 unsigned i = 0;
00653 double psr = 0;
00654 double dtmp1 = 0;
00655 double dtmp2 = 0;
00656 bool isEphAvailable = false;
00657 GPS_structEphemeris eph;
00658
00659 memset( &eph, 0, sizeof(eph) );
00660
00661 if( rxData == NULL )
00662 return false;
00663
00664 if( rxBaseData != NULL )
00665 {
00666
00667
00668 for( i = 0; i < rxBaseData->m_nrValidObs; i++ )
00669 {
00670 if( rxBaseData->m_ObsArray[i].flags.isActive )
00671 {
00672 if( rxBaseData->m_ObsArray[i].system == GNSS_GPS && rxBaseData->m_ObsArray[i].freqType == GNSS_GPSL1 )
00673 {
00674
00675
00676
00677
00678 rxBaseData->m_ObsArray[i].week = rxBaseData->m_pvt.time.gps_week;
00679
00680
00681 if( rxBaseData->m_ObsArray[i].flags.isCodeLocked & rxBaseData->m_ObsArray[i].flags.isPsrValid )
00682 {
00683 psr = rxBaseData->m_ObsArray[i].psr;
00684 }
00685 else
00686 {
00687 psr = 0.070*LIGHTSPEED;
00688 }
00689
00690 rxBaseData->m_ObsArray[i].tow = rxBaseData->m_pvt.time.gps_tow - psr/LIGHTSPEED;
00691
00692
00693 if( rxBaseData->m_ObsArray[i].tow < 0 )
00694 {
00695 rxBaseData->m_ObsArray[i].tow += SECONDS_IN_WEEK;
00696 rxBaseData->m_ObsArray[i].week = rxBaseData->m_pvt.time.gps_week - 1;
00697 }
00698 else if( rxBaseData->m_ObsArray[i].tow > SECONDS_IN_WEEK )
00699 {
00700 rxBaseData->m_ObsArray[i].tow -= SECONDS_IN_WEEK;
00701 rxBaseData->m_ObsArray[i].week = rxBaseData->m_pvt.time.gps_week + 1;
00702 }
00703
00704
00705 if( !rxBaseData->m_EphAlmArray.GetEphemeris( rxBaseData->m_ObsArray[i].id, eph, isEphAvailable ) )
00706 return false;
00707 if( !isEphAvailable )
00708 {
00709 rxBaseData->m_ObsArray[i].satellite.isValid = false;
00710 rxBaseData->m_ObsArray[i].flags.isEphemerisValid = false;
00711 continue;
00712 }
00713
00714
00715 if( eph.week < 1024 )
00716 eph.week += 1024;
00717
00718
00719
00720 dtmp1 = rxBaseData->m_ObsArray[i].week*SECONDS_IN_WEEK + rxBaseData->m_ObsArray[i].tow;
00721 dtmp2 = eph.week*SECONDS_IN_WEEK + eph.toe;
00722 rxBaseData->m_ObsArray[i].satellite.ageOfEph = static_cast<int>(dtmp1 - dtmp2);
00723 if( rxBaseData->m_ObsArray[i].satellite.ageOfEph > static_cast<int>(rxBaseData->m_maxAgeEphemeris) )
00724 {
00725 rxBaseData->m_ObsArray[i].satellite.isValid = false;
00726 rxBaseData->m_ObsArray[i].flags.isEphemerisValid = false;
00727 continue;
00728 }
00729 else
00730 {
00731 rxBaseData->m_ObsArray[i].satellite.isValid = true;
00732 }
00733
00734 rxBaseData->m_ObsArray[i].flags.isEphemerisValid = true;
00735
00736
00737 GPS_ComputeSatellitePositionVelocityAzimuthElevationDoppler_BasedOnEphmerisData(
00738 rxBaseData->m_pvt.x,
00739 rxBaseData->m_pvt.y,
00740 rxBaseData->m_pvt.z,
00741 rxBaseData->m_ObsArray[i].week,
00742 rxBaseData->m_ObsArray[i].tow,
00743 eph.week,
00744 eph.toe,
00745 eph.toc,
00746 eph.af0,
00747 eph.af1,
00748 eph.af2,
00749 eph.tgd,
00750 eph.m0,
00751 eph.delta_n,
00752 eph.ecc,
00753 eph.sqrta,
00754 eph.omega0,
00755 eph.i0,
00756 eph.w,
00757 eph.omegadot,
00758 eph.idot,
00759 eph.cuc,
00760 eph.cus,
00761 eph.crc,
00762 eph.crs,
00763 eph.cic,
00764 eph.cis,
00765 &rxBaseData->m_ObsArray[i].satellite.clk,
00766 &rxBaseData->m_ObsArray[i].satellite.clkdrift,
00767 &rxBaseData->m_ObsArray[i].satellite.x,
00768 &rxBaseData->m_ObsArray[i].satellite.y,
00769 &rxBaseData->m_ObsArray[i].satellite.z,
00770 &rxBaseData->m_ObsArray[i].satellite.vx,
00771 &rxBaseData->m_ObsArray[i].satellite.vy,
00772 &rxBaseData->m_ObsArray[i].satellite.vz,
00773 &rxBaseData->m_ObsArray[i].satellite.azimuth,
00774 &rxBaseData->m_ObsArray[i].satellite.elevation,
00775 &rxBaseData->m_ObsArray[i].satellite.doppler
00776 );
00777
00778 rxBaseData->m_ObsArray[i].corrections.prcSatClk = static_cast<float>(rxBaseData->m_ObsArray[i].satellite.clk);
00779 rxBaseData->m_ObsArray[i].corrections.rrcSatClkDrift = static_cast<float>(rxBaseData->m_ObsArray[i].satellite.clkdrift);
00780
00781
00782 GPS_ComputeUserToSatelliteRangeAndRangeRate(
00783 rxBaseData->m_pvt.x,
00784 rxBaseData->m_pvt.y,
00785 rxBaseData->m_pvt.z,
00786 rxBaseData->m_pvt.vx,
00787 rxBaseData->m_pvt.vy,
00788 rxBaseData->m_pvt.vz,
00789 rxBaseData->m_ObsArray[i].satellite.x,
00790 rxBaseData->m_ObsArray[i].satellite.y,
00791 rxBaseData->m_ObsArray[i].satellite.z,
00792 rxBaseData->m_ObsArray[i].satellite.vx,
00793 rxBaseData->m_ObsArray[i].satellite.vy,
00794 rxBaseData->m_ObsArray[i].satellite.vz,
00795 &rxBaseData->m_ObsArray[i].range,
00796 &rxBaseData->m_ObsArray[i].rangerate );
00797 }
00798 }
00799 }
00800 }
00801
00802
00803
00804 nrValidEph = 0;
00805 for( i = 0; i < rxData->m_nrValidObs; i++ )
00806 {
00807 if( rxData->m_ObsArray[i].flags.isActive )
00808 {
00809 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
00810 {
00811
00812
00813
00814
00815 rxData->m_ObsArray[i].week = rxData->m_pvt.time.gps_week;
00816
00817
00818 if( rxData->m_ObsArray[i].flags.isCodeLocked & rxData->m_ObsArray[i].flags.isPsrValid )
00819 {
00820 psr = rxData->m_ObsArray[i].psr;
00821 }
00822 else
00823 {
00824 psr = 0.070*LIGHTSPEED;
00825 }
00826
00827 rxData->m_ObsArray[i].tow = rxData->m_pvt.time.gps_tow - psr/LIGHTSPEED;
00828
00829
00830 if( rxData->m_ObsArray[i].tow < 0 )
00831 {
00832 rxData->m_ObsArray[i].tow += SECONDS_IN_WEEK;
00833 rxData->m_ObsArray[i].week = rxData->m_pvt.time.gps_week - 1;
00834 }
00835 else if( rxData->m_ObsArray[i].tow > SECONDS_IN_WEEK )
00836 {
00837 rxData->m_ObsArray[i].tow -= SECONDS_IN_WEEK;
00838 rxData->m_ObsArray[i].week = rxData->m_pvt.time.gps_week + 1;
00839 }
00840
00841 if( rxBaseData != NULL )
00842 {
00843
00844 if( !rxBaseData->m_EphAlmArray.GetEphemeris( rxData->m_ObsArray[i].id, eph, isEphAvailable ) )
00845 return false;
00846 if( !isEphAvailable )
00847 {
00848
00849 if( !rxData->m_EphAlmArray.GetEphemeris( rxData->m_ObsArray[i].id, eph, isEphAvailable ) )
00850 return false;
00851 if( !isEphAvailable )
00852 {
00853 rxData->m_ObsArray[i].satellite.isValid = false;
00854 rxData->m_ObsArray[i].flags.isEphemerisValid = false;
00855 continue;
00856 }
00857 }
00858 }
00859 else
00860 {
00861
00862 if( !rxData->m_EphAlmArray.GetEphemeris( rxData->m_ObsArray[i].id, eph, isEphAvailable ) )
00863 return false;
00864 if( !isEphAvailable )
00865 {
00866 rxData->m_ObsArray[i].satellite.isValid = false;
00867 rxData->m_ObsArray[i].flags.isEphemerisValid = false;
00868 continue;
00869 }
00870 }
00871
00872 rxData->m_ObsArray[i].flags.isEphemerisValid = true;
00873
00874
00875 if( eph.week < 1024 )
00876 eph.week += 1024;
00877
00878
00879 dtmp1 = rxData->m_ObsArray[i].week*SECONDS_IN_WEEK + rxData->m_ObsArray[i].tow;
00880 dtmp2 = eph.week*SECONDS_IN_WEEK + eph.toe;
00881 rxData->m_ObsArray[i].satellite.ageOfEph = static_cast<int>(dtmp1 - dtmp2);
00882 if( rxData->m_ObsArray[i].satellite.ageOfEph > static_cast<int>(rxData->m_maxAgeEphemeris) )
00883 {
00884 rxData->m_ObsArray[i].satellite.isValid = false;
00885 rxData->m_ObsArray[i].flags.isEphemerisValid = false;
00886 continue;
00887 }
00888 else
00889 {
00890 rxData->m_ObsArray[i].satellite.isValid = true;
00891 }
00892
00893
00894 GPS_ComputeSatellitePositionVelocityAzimuthElevationDoppler_BasedOnEphmerisData(
00895 rxData->m_pvt.x,
00896 rxData->m_pvt.y,
00897 rxData->m_pvt.z,
00898 rxData->m_ObsArray[i].week,
00899 rxData->m_ObsArray[i].tow,
00900 eph.week,
00901 eph.toe,
00902 eph.toc,
00903 eph.af0,
00904 eph.af1,
00905 eph.af2,
00906 eph.tgd,
00907 eph.m0,
00908 eph.delta_n,
00909 eph.ecc,
00910 eph.sqrta,
00911 eph.omega0,
00912 eph.i0,
00913 eph.w,
00914 eph.omegadot,
00915 eph.idot,
00916 eph.cuc,
00917 eph.cus,
00918 eph.crc,
00919 eph.crs,
00920 eph.cic,
00921 eph.cis,
00922 &rxData->m_ObsArray[i].satellite.clk,
00923 &rxData->m_ObsArray[i].satellite.clkdrift,
00924 &rxData->m_ObsArray[i].satellite.x,
00925 &rxData->m_ObsArray[i].satellite.y,
00926 &rxData->m_ObsArray[i].satellite.z,
00927 &rxData->m_ObsArray[i].satellite.vx,
00928 &rxData->m_ObsArray[i].satellite.vy,
00929 &rxData->m_ObsArray[i].satellite.vz,
00930 &rxData->m_ObsArray[i].satellite.azimuth,
00931 &rxData->m_ObsArray[i].satellite.elevation,
00932 &rxData->m_ObsArray[i].satellite.doppler
00933 );
00934
00935 rxData->m_ObsArray[i].corrections.prcSatClk = static_cast<float>(rxData->m_ObsArray[i].satellite.clk);
00936 rxData->m_ObsArray[i].corrections.rrcSatClkDrift = static_cast<float>(rxData->m_ObsArray[i].satellite.clkdrift);
00937
00938
00939 GPS_ComputeUserToSatelliteRangeAndRangeRate(
00940 rxData->m_pvt.x,
00941 rxData->m_pvt.y,
00942 rxData->m_pvt.z,
00943 rxData->m_pvt.vx,
00944 rxData->m_pvt.vy,
00945 rxData->m_pvt.vz,
00946 rxData->m_ObsArray[i].satellite.x,
00947 rxData->m_ObsArray[i].satellite.y,
00948 rxData->m_ObsArray[i].satellite.z,
00949 rxData->m_ObsArray[i].satellite.vx,
00950 rxData->m_ObsArray[i].satellite.vy,
00951 rxData->m_ObsArray[i].satellite.vz,
00952 &rxData->m_ObsArray[i].range,
00953 &rxData->m_ObsArray[i].rangerate );
00954
00955 nrValidEph++;
00956 }
00957 }
00958 }
00959 return true;
00960 }
00961
00962 bool GNSS_Estimator::DetermineAtmosphericCorrections_GPSL1(
00963 GNSS_RxData &rxData
00964 )
00965 {
00966 unsigned i = 0;
00967 double zenith_dry_delay = 0;
00968 double zenith_wet_delay = 0;
00969 double dtmp1 = 0;
00970 double dtmp2 = 0;
00971
00972
00973 TROPOSPHERE_DetermineZenithDelayValues_WAAS_Model(
00974 rxData.m_pvt.latitude,
00975 rxData.m_pvt.height,
00976 rxData.m_pvt.time.day_of_year,
00977 &zenith_dry_delay,
00978 &zenith_wet_delay
00979 );
00980
00981 for( i = 0; i < rxData.m_nrValidObs; i++ )
00982 {
00983 if( rxData.m_ObsArray[i].flags.isActive )
00984 {
00985 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
00986 {
00987 if( rxData.m_ObsArray[i].flags.isEphemerisValid )
00988 {
00989
00990 TROPOSPHERE_GetDryAndWetDelay_UsingThe_UNBabc_MappingFunction(
00991 zenith_dry_delay,
00992 zenith_wet_delay,
00993 rxData.m_ObsArray[i].satellite.elevation,
00994 rxData.m_pvt.latitude,
00995 rxData.m_pvt.height,
00996 &dtmp1,
00997 &dtmp2
00998 );
00999
01000 rxData.m_ObsArray[i].corrections.prcTropoDry = static_cast<float>(dtmp1);
01001 rxData.m_ObsArray[i].corrections.prcTropoWet = static_cast<float>(dtmp2);
01002
01003 if( rxData.m_klobuchar.isValid )
01004 {
01005
01006 IONOSPHERE_GetL1KlobucharCorrection(
01007 rxData.m_klobuchar.alpha0,
01008 rxData.m_klobuchar.alpha1,
01009 rxData.m_klobuchar.alpha2,
01010 rxData.m_klobuchar.alpha3,
01011 rxData.m_klobuchar.beta0,
01012 rxData.m_klobuchar.beta1,
01013 rxData.m_klobuchar.beta2,
01014 rxData.m_klobuchar.beta3,
01015 rxData.m_pvt.latitude,
01016 rxData.m_pvt.longitude,
01017 rxData.m_ObsArray[i].satellite.elevation,
01018 rxData.m_ObsArray[i].satellite.azimuth,
01019 rxData.m_pvt.time.gps_tow,
01020 &dtmp1
01021 );
01022 rxData.m_ObsArray[i].corrections.prcIono = static_cast<float>(dtmp1);
01023 }
01024 }
01025 }
01026 }
01027 }
01028 return true;
01029 }
01030
01031
01032
01033 bool GNSS_Estimator::DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1(
01034 GNSS_RxData &rxData,
01035 unsigned &nrUsablePseudoranges
01036 )
01037 {
01038 unsigned i = 0;
01039 unsigned char isGood = 0;
01040
01041 rxData.m_pvt.nrPsrObsAvailable = 0;
01042 rxData.m_pvt.nrPsrObsUsed = 0;
01043 rxData.m_pvt.nrPsrObsRejected = 0;
01044
01045 nrUsablePseudoranges = 0;
01046 for( i = 0; i < rxData.m_nrValidObs; i++ )
01047 {
01048 if( rxData.m_ObsArray[i].flags.isActive )
01049 {
01050 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01051 {
01052 if( rxData.m_ObsArray[i].satellite.elevation < rxData.m_elevationMask )
01053 {
01054 rxData.m_ObsArray[i].flags.isAboveElevationMask = 0;
01055 }
01056 else
01057 {
01058 rxData.m_ObsArray[i].flags.isAboveElevationMask = 1;
01059 }
01060
01061 if( rxData.m_ObsArray[i].cno < rxData.m_cnoMask )
01062 {
01063 rxData.m_ObsArray[i].flags.isAboveCNoMask = 0;
01064 }
01065 else
01066 {
01067 rxData.m_ObsArray[i].flags.isAboveCNoMask = 1;
01068 }
01069
01070 if( rxData.m_ObsArray[i].locktime < rxData.m_locktimeMask )
01071 {
01072 rxData.m_ObsArray[i].flags.isAboveLockTimeMask = 0;
01073 }
01074 else
01075 {
01076 rxData.m_ObsArray[i].flags.isAboveLockTimeMask = 1;
01077 }
01078
01079 isGood =
01080 rxData.m_ObsArray[i].flags.isCodeLocked &
01081 rxData.m_ObsArray[i].flags.isPsrValid &
01082 rxData.m_ObsArray[i].flags.isAboveElevationMask &
01083 rxData.m_ObsArray[i].flags.isAboveCNoMask &
01084 rxData.m_ObsArray[i].flags.isAboveLockTimeMask &
01085 rxData.m_ObsArray[i].flags.isNotUserRejected &
01086 rxData.m_ObsArray[i].flags.isNotPsrRejected &
01087 rxData.m_ObsArray[i].flags.isEphemerisValid;
01088 if( isGood )
01089 {
01090 rxData.m_ObsArray[i].flags.isPsrUsedInSolution = 1;
01091 nrUsablePseudoranges++;
01092 }
01093 else
01094 {
01095 rxData.m_ObsArray[i].flags.isPsrUsedInSolution = 0;
01096 }
01097 }
01098 }
01099 }
01100 rxData.m_pvt.nrPsrObsAvailable = nrUsablePseudoranges;
01101 return true;
01102 }
01103
01104
01105 bool GNSS_Estimator::DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1(
01106 GNSS_RxData &rxData,
01107 unsigned &nrUsableDopplers
01108 )
01109 {
01110 unsigned i = 0;
01111 unsigned char isGood = 0;
01112
01113 rxData.m_pvt.nrDopplerObsAvailable = 0;
01114 rxData.m_pvt.nrDopplerObsUsed = 0;
01115 rxData.m_pvt.nrDopplerObsRejected = 0;
01116
01117 nrUsableDopplers = 0;
01118 for( i = 0; i < rxData.m_nrValidObs; i++ )
01119 {
01120 if( rxData.m_ObsArray[i].flags.isActive )
01121 {
01122 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01123 {
01124 isGood =
01125 rxData.m_ObsArray[i].flags.isCodeLocked &
01126 rxData.m_ObsArray[i].flags.isDopplerValid &
01127 rxData.m_ObsArray[i].flags.isAboveElevationMask &
01128 rxData.m_ObsArray[i].flags.isAboveCNoMask &
01129 rxData.m_ObsArray[i].flags.isAboveLockTimeMask &
01130 rxData.m_ObsArray[i].flags.isNotUserRejected &
01131 rxData.m_ObsArray[i].flags.isNotDopplerRejected &
01132 rxData.m_ObsArray[i].flags.isEphemerisValid;
01133 if( isGood )
01134 {
01135 rxData.m_ObsArray[i].flags.isDopplerUsedInSolution = 1;
01136 nrUsableDopplers++;
01137 }
01138 else
01139 {
01140 rxData.m_ObsArray[i].flags.isDopplerUsedInSolution = 0;
01141 }
01142 }
01143 }
01144 }
01145 rxData.m_pvt.nrDopplerObsAvailable = nrUsableDopplers;
01146 return true;
01147 }
01148
01149
01150 bool GNSS_Estimator::DetermineUsableAdrMeasurements_GPSL1(
01151 GNSS_RxData &rxData,
01152 unsigned &nrUsableAdr
01153 )
01154 {
01155 unsigned i = 0;
01156 unsigned char isGood = 0;
01157
01158 rxData.m_pvt.nrAdrObsAvailable = 0;
01159 rxData.m_pvt.nrAdrObsUsed = 0;
01160 rxData.m_pvt.nrAdrObsRejected = 0;
01161
01162
01163 rxData.CheckForCycleSlips_UsingPhaseRatePrediction( GNSS_CYCLESLIP_THREADHOLD );
01164
01165 nrUsableAdr = 0;
01166 for( i = 0; i < rxData.m_nrValidObs; i++ )
01167 {
01168 if( rxData.m_ObsArray[i].flags.isActive )
01169 {
01170 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01171 {
01172 if( rxData.m_ObsArray[i].satellite.elevation < rxData.m_elevationMask )
01173 rxData.m_ObsArray[i].flags.isAboveElevationMask = 0;
01174 else
01175 rxData.m_ObsArray[i].flags.isAboveElevationMask = 1;
01176
01177 if( rxData.m_ObsArray[i].cno < rxData.m_cnoMask )
01178 rxData.m_ObsArray[i].flags.isAboveCNoMask = 0;
01179 else
01180 rxData.m_ObsArray[i].flags.isAboveCNoMask = 1;
01181
01182 if( rxData.m_ObsArray[i].locktime < rxData.m_locktimeMask )
01183 rxData.m_ObsArray[i].flags.isAboveLockTimeMask = 0;
01184 else
01185 rxData.m_ObsArray[i].flags.isAboveLockTimeMask = 1;
01186
01187 isGood =
01188 rxData.m_ObsArray[i].flags.isCodeLocked &
01189 rxData.m_ObsArray[i].flags.isPhaseLocked &
01190 rxData.m_ObsArray[i].flags.isParityValid &
01191 rxData.m_ObsArray[i].flags.isAdrValid &
01192 rxData.m_ObsArray[i].flags.isAboveElevationMask &
01193 rxData.m_ObsArray[i].flags.isAboveCNoMask &
01194 rxData.m_ObsArray[i].flags.isAboveLockTimeMask &
01195 rxData.m_ObsArray[i].flags.isNotUserRejected &
01196 rxData.m_ObsArray[i].flags.isNotAdrRejected &
01197 rxData.m_ObsArray[i].flags.isEphemerisValid;
01198 if( isGood )
01199 {
01200 rxData.m_ObsArray[i].flags.isAdrUsedInSolution = 1;
01201 nrUsableAdr++;
01202 }
01203 else
01204 {
01205 rxData.m_ObsArray[i].flags.isAdrUsedInSolution = 0;
01206 }
01207 }
01208 }
01209 }
01210 rxData.m_pvt.nrAdrObsAvailable = nrUsableAdr;
01211 return true;
01212 }
01213
01214
01215 bool GNSS_Estimator::DetermineDesignMatrixForThePositionSolution_GPSL1(
01216 GNSS_RxData &rxData,
01217 const unsigned nrRowsInH,
01218 Matrix &H
01219 )
01220 {
01221 unsigned i = 0;
01222 unsigned j = 0;
01223
01224
01225 if( H.GetNrRows() != nrRowsInH || H.GetNrCols() != 4 )
01226 {
01227 if( !H.Resize( nrRowsInH, 4 ) )
01228 return false;
01229 }
01230
01231 for( i = 0; i < rxData.m_nrValidObs; i++ )
01232 {
01233 if( rxData.m_ObsArray[i].flags.isActive )
01234 {
01235 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01236 {
01237 if( rxData.m_ObsArray[i].flags.isPsrUsedInSolution )
01238 {
01239
01240 if( j >= nrRowsInH )
01241 return false;
01242
01243 NAVIGATION_ComputeDerivativesOf_Range_WithRespectToLatitudeLongitudeHeight(
01244 rxData.m_pvt.latitude,
01245 rxData.m_pvt.longitude,
01246 rxData.m_pvt.height,
01247 rxData.m_ObsArray[i].satellite.x,
01248 rxData.m_ObsArray[i].satellite.y,
01249 rxData.m_ObsArray[i].satellite.z,
01250 &H[j][0],
01251 &H[j][1],
01252 &H[j][2],
01253 &rxData.m_ObsArray[i].range
01254 );
01255 H[j][3] = 1.0;
01256
01257
01258 rxData.m_ObsArray[i].H_p[0] = H[j][0];
01259 rxData.m_ObsArray[i].H_p[1] = H[j][1];
01260 rxData.m_ObsArray[i].H_p[2] = H[j][2];
01261
01262 j++;
01263 }
01264 }
01265 }
01266 }
01267
01268
01269 if( rxData.m_pvt.isPositionConstrained )
01270 {
01271 if( j + 3 > nrRowsInH )
01272 return false;
01273
01274 H[j][0] = 1.0;
01275 H[j][1] = 0.0;
01276 H[j][2] = 0.0;
01277 H[j][3] = 0.0;
01278 j++;
01279 H[j][0] = 0.0;
01280 H[j][1] = 1.0;
01281 H[j][2] = 0.0;
01282 H[j][3] = 0.0;
01283 j++;
01284 H[j][0] = 0.0;
01285 H[j][1] = 0.0;
01286 H[j][2] = 1.0;
01287 H[j][3] = 0.0;
01288 j++;
01289 }
01290 else if( rxData.m_pvt.isHeightConstrained )
01291 {
01292 if( j + 1 > nrRowsInH )
01293 return false;
01294
01295 H[j][0] = 0.0;
01296 H[j][1] = 0.0;
01297 H[j][2] = 1.0;
01298 H[j][3] = 0.0;
01299 j++;
01300 }
01301
01302 return true;
01303 }
01304
01305
01306 bool GNSS_Estimator::DetermineMeasurementWeightMatrixForThePositionSolution_GPSL1(
01307 GNSS_RxData &rxData,
01308 const unsigned n,
01309 Matrix &W
01310 )
01311 {
01312 unsigned i = 0;
01313 unsigned j = 0;
01314
01315
01316 if( W.GetNrRows() != n || W.GetNrCols() != n )
01317 {
01318 if( !W.Resize( n, n ) )
01319 return false;
01320 }
01321
01322 for( i = 0; i < rxData.m_nrValidObs; i++ )
01323 {
01324 if( rxData.m_ObsArray[i].flags.isActive )
01325 {
01326 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01327 {
01328 if( rxData.m_ObsArray[i].flags.isPsrUsedInSolution )
01329 {
01330
01331 if( j >= n )
01332 return false;
01333
01334
01335 if( rxData.m_ObsArray[i].stdev_psr == 0.0 )
01336 return false;
01337
01338 W[j][j] = 1.0/(rxData.m_ObsArray[i].stdev_psr*rxData.m_ObsArray[i].stdev_psr);
01339 j++;
01340 }
01341 }
01342 }
01343 }
01344
01345
01346 if( rxData.m_pvt.isPositionConstrained )
01347 {
01348 if( j + 3 > n )
01349 return false;
01350
01351 W[j][j] = 1.0/(rxData.m_pvt.std_lat*rxData.m_pvt.std_lat);
01352 j++;
01353 W[j][j] = 1.0/(rxData.m_pvt.std_lon*rxData.m_pvt.std_lon);
01354 j++;
01355 W[j][j] = 1.0/(rxData.m_pvt.std_hgt*rxData.m_pvt.std_hgt);
01356 j++;
01357 }
01358 else if( rxData.m_pvt.isHeightConstrained )
01359 {
01360 if( j + 1 > n )
01361 return false;
01362
01363 W[j][j] = 1.0/(rxData.m_pvt.std_hgt*rxData.m_pvt.std_hgt);
01364 j++;
01365 }
01366
01367 return true;
01368 }
01369
01370
01371 bool GNSS_Estimator::DetermineMeasurementVarianceCovarianceMatrixForThePositionSolution_GPSL1(
01372 GNSS_RxData &rxData,
01373 const unsigned n,
01374 Matrix &R
01375 )
01376 {
01377 unsigned i = 0;
01378 unsigned j = 0;
01379
01380
01381 if( R.GetNrRows() != n || R.GetNrCols() != n )
01382 {
01383 if( !R.Resize( n, n ) )
01384 return false;
01385 }
01386
01387 for( i = 0; i < rxData.m_nrValidObs; i++ )
01388 {
01389 if( rxData.m_ObsArray[i].flags.isActive )
01390 {
01391 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
01392 {
01393 if( rxData.m_ObsArray[i].flags.isPsrUsedInSolution )
01394 {
01395
01396 if( j >= n )
01397 return false;
01398
01399
01400 if( rxData.m_ObsArray[i].stdev_psr == 0.0 )
01401 return false;
01402
01403 R[j][j] = rxData.m_ObsArray[i].stdev_psr*rxData.m_ObsArray[i].stdev_psr;
01404 j++;
01405 }
01406 }
01407 }
01408 }
01409
01410
01411 if( rxData.m_pvt.isPositionConstrained )
01412 {
01413 if( j + 3 > n )
01414 return false;
01415
01416 R[j][j] = rxData.m_pvt.std_lat*rxData.m_pvt.std_lat;
01417 j++;
01418 R[j][j] = rxData.m_pvt.std_lon*rxData.m_pvt.std_lon;
01419 j++;
01420 R[j][j] = rxData.m_pvt.std_hgt*rxData.m_pvt.std_hgt;
01421 j++;
01422 }
01423 else if( rxData.m_pvt.isHeightConstrained )
01424 {
01425 if( j + 1 > n )
01426 return false;
01427
01428 R[j][j] = rxData.m_pvt.std_hgt*rxData.m_pvt.std_hgt;
01429 j++;
01430 }
01431
01432 return true;
01433 }
01434
01435
01436
01437 bool GNSS_Estimator::DeterminePseudorangeMisclosures_GPSL1(
01438 GNSS_RxData *rxData,
01439 GNSS_RxData *rxBaseData,
01440 const unsigned n,
01441 Matrix &w
01442 )
01443 {
01444 unsigned i = 0;
01445 unsigned j = 0;
01446 int k = 0;
01447 double psr_base = 0;
01448 double range_base = 0;
01449 double psr_measured = 0;
01450 double psr_computed = 0;
01451
01452
01453 if( w.GetNrRows() != n || w.GetNrCols() != 1 )
01454 {
01455 if( !w.Resize( n, 1 ) )
01456 return false;
01457 }
01458
01459 for( i = 0; i < rxData->m_nrValidObs; i++ )
01460 {
01461 if( rxData->m_ObsArray[i].flags.isActive )
01462 {
01463 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
01464 {
01465
01466 psr_measured = rxData->m_ObsArray[i].psr;
01467
01468
01469 psr_measured += rxData->m_ObsArray[i].satellite.clk;
01470
01471
01472
01473 if( rxData->m_ObsArray[i].flags.useBroadcastIonoCorrection )
01474 {
01475
01476 psr_measured -= rxData->m_ObsArray[i].corrections.prcIono;
01477 }
01478
01479
01480
01481 if( rxData->m_ObsArray[i].flags.useTropoCorrection )
01482 {
01483
01484 psr_measured -= rxData->m_ObsArray[i].corrections.prcTropoDry;
01485 psr_measured -= rxData->m_ObsArray[i].corrections.prcTropoWet;
01486 }
01487
01488 range_base = 0;
01489 if( rxBaseData != NULL )
01490 {
01491 if( rxData->m_ObsArray[i].flags.isDifferentialPsrAvailable )
01492 {
01493 k = rxData->m_ObsArray[i].index_differential;
01494 if( k != -1 )
01495 {
01496 psr_base = rxBaseData->m_ObsArray[k].psr;
01497 psr_base += rxBaseData->m_ObsArray[k].satellite.clk;
01498
01499
01500
01501 if( rxBaseData->m_ObsArray[k].flags.useBroadcastIonoCorrection )
01502 {
01503
01504 psr_base -= rxBaseData->m_ObsArray[k].corrections.prcIono;
01505 }
01506
01507
01508
01509 if( rxBaseData->m_ObsArray[k].flags.useTropoCorrection )
01510 {
01511
01512 psr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoDry;
01513 psr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoWet;
01514 }
01515
01516 range_base = rxBaseData->m_ObsArray[k].range;
01517
01518
01519 psr_measured -= psr_base;
01520 }
01521 }
01522 }
01523
01524
01525
01526
01527 psr_computed = rxData->m_ObsArray[i].range - range_base + rxData->m_pvt.clockOffset;
01528
01529
01530 rxData->m_ObsArray[i].psr_misclosure = psr_measured - psr_computed;
01531
01532 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
01533 {
01534
01535 if( j >= n )
01536 return false;
01537
01538 w[j] = rxData->m_ObsArray[i].psr_misclosure;
01539 j++;
01540 }
01541 }
01542 else
01543 {
01544 rxData->m_ObsArray[i].psr_misclosure = 0.0;
01545 }
01546 }
01547 }
01548
01549
01550 if( rxData->m_pvt.isPositionConstrained )
01551 {
01552 if( j + 3 > n )
01553 return false;
01554
01555 double N;
01556 double M;
01557 double diff;
01558
01559 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
01560 GEODESY_REFERENCE_ELLIPSE_WGS84,
01561 rxData->m_prev_pvt.latitude,
01562 &N );
01563 GEODESY_ComputeMeridianRadiusOfCurvature(
01564 GEODESY_REFERENCE_ELLIPSE_WGS84,
01565 rxData->m_prev_pvt.latitude,
01566 &M );
01567
01568 diff = (rxData->m_prev_pvt.latitude - rxData->m_pvt.latitude);
01569 diff *= ( M + rxData->m_prev_pvt.height );
01570 w[j] = diff;
01571 j++;
01572 diff = (rxData->m_prev_pvt.longitude - rxData->m_pvt.longitude );
01573 diff *= (N + rxData->m_prev_pvt.height)*cos(rxData->m_prev_pvt.latitude);
01574 w[j] = diff;
01575 j++;
01576 w[j] = rxData->m_prev_pvt.height - rxData->m_pvt.height;
01577 j++;
01578 }
01579 else if( rxData->m_pvt.isHeightConstrained )
01580 {
01581 if( j + 1 > n )
01582 return false;
01583
01584 w[j] = rxData->m_prev_pvt.height - rxData->m_pvt.height;
01585 j++;
01586 }
01587
01588
01589 return true;
01590 }
01591
01592
01593 bool GNSS_Estimator::DetermineBetweenReceiverDifferentialIndex(
01594 GNSS_RxData *rxData,
01595 GNSS_RxData *rxBaseData,
01596 const bool setToUseOnlyDifferential
01597 )
01598 {
01599 unsigned i = 0;
01600 unsigned j = 0;
01601
01602
01603
01604 for( i = 0; i < rxData->m_nrValidObs; i++ )
01605 {
01606 rxData->m_ObsArray[i].index_differential = -1;
01607 rxData->m_ObsArray[i].flags.isDifferentialPsrAvailable = 0;
01608 rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable = 0;
01609 rxData->m_ObsArray[i].flags.isDifferentialDopplerAvailable = 0;
01610 }
01611 for( i = 0; i < rxBaseData->m_nrValidObs; i++ )
01612 {
01613 rxBaseData->m_ObsArray[i].index_differential = -1;
01614 rxBaseData->m_ObsArray[i].flags.isDifferentialPsrAvailable = 0;
01615 rxBaseData->m_ObsArray[i].flags.isDifferentialAdrAvailable = 0;
01616 rxBaseData->m_ObsArray[i].flags.isDifferentialDopplerAvailable = 0;
01617 }
01618 if( rxBaseData == NULL )
01619 return true;
01620
01621 for( i = 0; i < rxData->m_nrValidObs; i++ )
01622 {
01623 if( rxData->m_ObsArray[i].flags.isActive )
01624 {
01625
01626 for( j = 0; j < rxBaseData->m_nrValidObs; j++ )
01627 {
01628 if( rxBaseData->m_ObsArray[j].flags.isActive )
01629 {
01630 if( rxData->m_ObsArray[i].system == rxBaseData->m_ObsArray[j].system &&
01631 rxData->m_ObsArray[i].codeType == rxBaseData->m_ObsArray[j].codeType &&
01632 rxData->m_ObsArray[i].freqType == rxBaseData->m_ObsArray[j].freqType &&
01633 rxData->m_ObsArray[i].id == rxBaseData->m_ObsArray[j].id )
01634 {
01635 rxData->m_ObsArray[i].index_differential = j;
01636 rxBaseData->m_ObsArray[j].index_differential = i;
01637
01638 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution &&
01639 rxBaseData->m_ObsArray[j].flags.isPsrUsedInSolution )
01640 {
01641 rxData->m_ObsArray[i].flags.isDifferentialPsrAvailable = 1;
01642 rxBaseData->m_ObsArray[j].flags.isDifferentialPsrAvailable = 1;
01643 }
01644
01645 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution &&
01646 rxBaseData->m_ObsArray[j].flags.isDopplerUsedInSolution )
01647 {
01648 rxData->m_ObsArray[i].flags.isDifferentialDopplerAvailable = 1;
01649 rxBaseData->m_ObsArray[j].flags.isDifferentialDopplerAvailable = 1;
01650 }
01651
01652 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution &&
01653 rxBaseData->m_ObsArray[j].flags.isAdrUsedInSolution )
01654 {
01655 rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable = 1;
01656 rxBaseData->m_ObsArray[j].flags.isDifferentialAdrAvailable = 1;
01657 }
01658
01659 break;
01660 }
01661 }
01662 }
01663 }
01664 }
01665
01666 if( setToUseOnlyDifferential )
01667 {
01668 for( i = 0; i < rxData->m_nrValidObs; i++ )
01669 {
01670
01671 if( rxData->m_ObsArray[i].flags.isActive )
01672 {
01673
01674 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
01675 {
01676 if( !rxData->m_ObsArray[i].flags.isDifferentialPsrAvailable )
01677 {
01678 rxData->m_ObsArray[i].flags.isPsrUsedInSolution = 0;
01679 }
01680 }
01681
01682 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
01683 {
01684 if( !rxData->m_ObsArray[i].flags.isDifferentialDopplerAvailable )
01685 {
01686 rxData->m_ObsArray[i].flags.isDifferentialDopplerAvailable = 0;
01687 }
01688 }
01689
01690 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
01691 {
01692 if( !rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
01693 {
01694 rxData->m_ObsArray[i].flags.isAdrUsedInSolution = 0;
01695 }
01696 }
01697
01698 }
01699
01700 }
01701 }
01702
01703 return true;
01704 }
01705
01706
01707 bool GNSS_Estimator::DetermineSingleDifferenceADR_Misclosures_GPSL1(
01708 GNSS_RxData *rxData,
01709 GNSS_RxData *rxBaseData,
01710 const unsigned n,
01711 Matrix &w
01712 )
01713 {
01714 unsigned i = 0;
01715 unsigned j = 0;
01716 int k = 0;
01717 double adr_base = 0;
01718 double range_base = 0;
01719 double adr_measured = 0;
01720 double adr_computed = 0;
01721
01722 if( n == 0 )
01723 return true;
01724
01725
01726 if( w.GetNrRows() != n || w.GetNrCols() != 1 )
01727 {
01728 if( !w.Resize( n, 1 ) )
01729 return false;
01730 }
01731
01732 for( i = 0; i < rxData->m_nrValidObs; i++ )
01733 {
01734 if( rxData->m_ObsArray[i].flags.isActive )
01735 {
01736 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
01737 {
01738
01739 adr_measured = rxData->m_ObsArray[i].adr * GPS_WAVELENGTHL1;
01740
01741
01742 adr_measured += rxData->m_ObsArray[i].satellite.clk;
01743
01744
01745
01746 if( rxData->m_ObsArray[i].flags.useBroadcastIonoCorrection )
01747 {
01748
01749 adr_measured += rxData->m_ObsArray[i].corrections.prcIono;
01750 }
01751
01752
01753
01754 if( rxData->m_ObsArray[i].flags.useTropoCorrection )
01755 {
01756
01757 adr_measured -= rxData->m_ObsArray[i].corrections.prcTropoDry;
01758 adr_measured -= rxData->m_ObsArray[i].corrections.prcTropoWet;
01759 }
01760
01761 range_base = 0;
01762 if( rxBaseData != NULL )
01763 {
01764 if( rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
01765 {
01766 k = rxData->m_ObsArray[i].index_differential;
01767 if( k != -1 )
01768 {
01769 adr_base = rxBaseData->m_ObsArray[k].adr * GPS_WAVELENGTHL1;
01770 adr_base += rxBaseData->m_ObsArray[k].satellite.clk;
01771
01772
01773
01774 if( rxBaseData->m_ObsArray[k].flags.useBroadcastIonoCorrection )
01775 {
01776
01777 adr_base += rxBaseData->m_ObsArray[k].corrections.prcIono;
01778 }
01779
01780
01781
01782 if( rxBaseData->m_ObsArray[k].flags.useTropoCorrection )
01783 {
01784
01785 adr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoDry;
01786 adr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoWet;
01787 }
01788
01789 range_base = rxBaseData->m_ObsArray[k].range;
01790
01791
01792 adr_measured -= adr_base;
01793 }
01794 }
01795 }
01796
01797
01798
01799
01800 adr_computed = rxData->m_ObsArray[i].range - range_base;
01801 adr_computed += rxData->m_pvt.clockOffset;
01802 adr_computed += rxData->m_ObsArray[i].ambiguity;
01803
01804
01805 rxData->m_ObsArray[i].adr_misclosure = adr_measured - adr_computed;
01806
01807 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
01808 {
01809
01810 if( j >= n )
01811 return false;
01812
01813 w[j] = rxData->m_ObsArray[i].adr_misclosure;
01814 j++;
01815 }
01816 }
01817 else
01818 {
01819 rxData->m_ObsArray[i].adr_misclosure = 0.0;
01820 }
01821 }
01822 }
01823 return true;
01824 }
01825
01826 bool GNSS_Estimator::DetermineDoubleDifferenceADR_Misclosures_GPSL1(
01827 GNSS_RxData *rxData,
01828 GNSS_RxData *rxBaseData,
01829 Matrix &subB,
01830 const unsigned n,
01831 Matrix &w
01832 )
01833 {
01834 unsigned i = 0;
01835 unsigned j = 0;
01836 int k = 0;
01837 double adr_base = 0;
01838 double range_base = 0;
01839 double adr_measured = 0;
01840 double adr_computed = 0;
01841
01842 if( n == 0 )
01843 return true;
01844
01845
01846 if( w.GetNrRows() != n || w.GetNrCols() != 1 )
01847 {
01848 if( !w.Resize( n, 1 ) )
01849 return false;
01850 }
01851
01852 for( i = 0; i < rxData->m_nrValidObs; i++ )
01853 {
01854 if( rxData->m_ObsArray[i].flags.isActive )
01855 {
01856 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
01857 {
01858
01859 adr_measured = rxData->m_ObsArray[i].adr * GPS_WAVELENGTHL1;
01860
01861
01862 adr_measured += rxData->m_ObsArray[i].satellite.clk;
01863
01864
01865
01866 if( rxData->m_ObsArray[i].flags.useBroadcastIonoCorrection )
01867 {
01868
01869 adr_measured += rxData->m_ObsArray[i].corrections.prcIono;
01870 }
01871
01872
01873
01874 if( rxData->m_ObsArray[i].flags.useTropoCorrection )
01875 {
01876
01877 adr_measured -= rxData->m_ObsArray[i].corrections.prcTropoDry;
01878 adr_measured -= rxData->m_ObsArray[i].corrections.prcTropoWet;
01879 }
01880
01881 range_base = 0;
01882 if( rxBaseData != NULL )
01883 {
01884 if( rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
01885 {
01886 k = rxData->m_ObsArray[i].index_differential;
01887 if( k != -1 )
01888 {
01889 adr_base = rxBaseData->m_ObsArray[k].adr * GPS_WAVELENGTHL1;
01890 adr_base += rxBaseData->m_ObsArray[k].satellite.clk;
01891
01892
01893
01894 if( rxBaseData->m_ObsArray[k].flags.useBroadcastIonoCorrection )
01895 {
01896
01897 adr_base += rxBaseData->m_ObsArray[k].corrections.prcIono;
01898 }
01899
01900
01901
01902 if( rxBaseData->m_ObsArray[k].flags.useTropoCorrection )
01903 {
01904
01905 adr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoDry;
01906 adr_base -= rxBaseData->m_ObsArray[k].corrections.prcTropoWet;
01907 }
01908
01909 range_base = rxBaseData->m_ObsArray[k].range;
01910
01911
01912 adr_measured -= adr_base;
01913 }
01914 }
01915 }
01916
01917
01918
01919
01920 adr_computed = rxData->m_ObsArray[i].range - range_base;
01921 adr_computed += rxData->m_pvt.clockOffset;
01922 adr_computed += rxData->m_ObsArray[i].ambiguity;
01923
01924
01925 rxData->m_ObsArray[i].adr_misclosure = adr_measured - adr_computed;
01926
01927 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
01928 {
01929
01930 if( j >= n )
01931 return false;
01932
01933 w[j] = rxData->m_ObsArray[i].adr_misclosure;
01934 j++;
01935 }
01936 }
01937 else
01938 {
01939 rxData->m_ObsArray[i].adr_misclosure = 0.0;
01940 }
01941 }
01942 }
01943 return true;
01944 }
01945
01946 bool GNSS_Estimator::DetermineDopplerMisclosures_GPSL1(
01947 GNSS_RxData *rxData,
01948 GNSS_RxData *rxBaseData,
01949 const unsigned n,
01950 Matrix &w
01951 )
01952 {
01953 unsigned i = 0;
01954 unsigned j = 0;
01955 int k = 0;
01956 double doppler_base = 0;
01957 double rangerate_base = 0;
01958 double doppler_measured = 0;
01959 double doppler_computed = 0;
01960
01961 if( n == 0 )
01962 return true;
01963
01964
01965 if( w.GetNrRows() != n || w.GetNrCols() != 1 )
01966 {
01967 if( !w.Resize( n, 1 ) )
01968 return false;
01969 }
01970 for( i = 0; i < rxData->m_nrValidObs; i++ )
01971 {
01972 if( rxData->m_ObsArray[i].flags.isActive )
01973 {
01974 rxData->m_ObsArray[i].doppler_misclosure = 0.0;
01975
01976 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
01977 {
01978
01979
01980
01981 doppler_measured = rxData->m_ObsArray[i].doppler * GPS_WAVELENGTHL1;
01982
01983
01984 doppler_measured += rxData->m_ObsArray[i].satellite.clkdrift;
01985
01986 rangerate_base = 0;
01987 if( rxBaseData != NULL )
01988 {
01989 doppler_base = 0;
01990 if( rxData->m_ObsArray[i].flags.isDifferentialDopplerAvailable )
01991 {
01992 k = rxData->m_ObsArray[i].index_differential;
01993 if( k != -1 )
01994 {
01995 doppler_base = rxBaseData->m_ObsArray[k].doppler * GPS_WAVELENGTHL1;
01996 rangerate_base = rxBaseData->m_ObsArray[k].rangerate;
01997 }
01998 doppler_measured -= doppler_base;
01999 }
02000 }
02001
02002
02003 doppler_computed = rxData->m_ObsArray[i].rangerate - rangerate_base + rxData->m_pvt.clockDrift;
02004
02005
02006 rxData->m_ObsArray[i].doppler_misclosure = doppler_measured - doppler_computed;
02007
02008 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
02009 {
02010 if( j >= n )
02011 return false;
02012
02013 w[j] = rxData->m_ObsArray[i].doppler_misclosure;
02014 j++;
02015 }
02016 }
02017 }
02018 }
02019
02020 if( rxData->m_pvt.isPositionConstrained )
02021 {
02022 if( j + 3 > n )
02023 return false;
02024
02025 w[j] = 0.0;
02026 j++;
02027 w[j] = 0.0;
02028 j++;
02029 w[j] = 0.0;
02030 j++;
02031 }
02032 else if( rxData->m_pvt.isHeightConstrained )
02033 {
02034 if( j + 1 > n )
02035 return false;
02036
02037 w[j] = 0.0;
02038 j++;
02039 }
02040
02041 return true;
02042 }
02043
02044
02045 bool GNSS_Estimator::DetermineDesignMatrixForTheVelocitySolution_GPSL1(
02046 GNSS_RxData &rxData,
02047 const unsigned n,
02048 Matrix &H
02049 )
02050 {
02051 unsigned i = 0;
02052 unsigned j = 0;
02053
02054 if( n == 0 )
02055 return true;
02056
02057
02058 if( H.GetNrRows() != n || H.GetNrCols() != 4 )
02059 {
02060 if( !H.Resize( n, 4 ) )
02061 return false;
02062 }
02063
02064 for( i = 0; i < rxData.m_nrValidObs; i++ )
02065 {
02066 if( rxData.m_ObsArray[i].flags.isActive )
02067 {
02068 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
02069 {
02070 if( rxData.m_ObsArray[i].flags.isDopplerUsedInSolution )
02071 {
02072
02073 if( j >= n )
02074 return false;
02075
02076 NAVIGATION_ComputeDerivativesOf_Range_WithRespectToLatitudeLongitudeHeight(
02077 rxData.m_pvt.latitude,
02078 rxData.m_pvt.longitude,
02079 rxData.m_pvt.height,
02080 rxData.m_ObsArray[i].satellite.x,
02081 rxData.m_ObsArray[i].satellite.y,
02082 rxData.m_ObsArray[i].satellite.z,
02083 &H[j][0],
02084 &H[j][1],
02085 &H[j][2],
02086 &rxData.m_ObsArray[i].range
02087 );
02088 H[j][0] *= -1.0;
02089 H[j][1] *= -1.0;
02090 H[j][2] *= -1.0;
02091 H[j][3] = 1.0;
02092
02093
02094 rxData.m_ObsArray[i].H_v[0] = H[j][0];
02095 rxData.m_ObsArray[i].H_v[1] = H[j][1];
02096 rxData.m_ObsArray[i].H_v[2] = H[j][2];
02097
02098 j++;
02099 }
02100 }
02101 }
02102 }
02103
02104 if( rxData.m_pvt.isPositionConstrained )
02105 {
02106 if( j + 3 > n )
02107 return false;
02108
02109 H[j][0] = 1.0;
02110 H[j][1] = 0.0;
02111 H[j][2] = 0.0;
02112 H[j][3] = 0.0;
02113 j++;
02114 H[j][0] = 0.0;
02115 H[j][1] = 1.0;
02116 H[j][2] = 0.0;
02117 H[j][3] = 0.0;
02118 j++;
02119 H[j][0] = 0.0;
02120 H[j][1] = 0.0;
02121 H[j][2] = 1.0;
02122 H[j][3] = 0.0;
02123 j++;
02124 }
02125 else if( rxData.m_pvt.isHeightConstrained )
02126 {
02127 if( j + 1 > n )
02128 return false;
02129
02130 H[j][0] = 0.0;
02131 H[j][1] = 0.0;
02132 H[j][2] = 1.0;
02133 H[j][3] = 0.0;
02134 j++;
02135 }
02136
02137 return true;
02138 }
02139
02140
02141 bool GNSS_Estimator::DetermineMeasurementWeightMatrixForTheVelocitySolution_GPSL1(
02142 GNSS_RxData &rxData,
02143 const unsigned n,
02144 Matrix &W
02145 )
02146 {
02147 unsigned i = 0;
02148 unsigned j = 0;
02149 double std_ms = 0.0;
02150
02151
02152 if( W.GetNrRows() != n || W.GetNrCols() != n )
02153 {
02154 if( !W.Resize( n, n ) )
02155 return false;
02156 }
02157
02158 for( i = 0; i < rxData.m_nrValidObs; i++ )
02159 {
02160 if( rxData.m_ObsArray[i].flags.isActive )
02161 {
02162 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
02163 {
02164 if( rxData.m_ObsArray[i].flags.isDopplerUsedInSolution )
02165 {
02166
02167 if( j >= n )
02168 return false;
02169
02170
02171 if( rxData.m_ObsArray[i].stdev_doppler == 0.0 )
02172 return false;
02173
02174 std_ms = rxData.m_ObsArray[i].stdev_doppler * GPS_WAVELENGTHL1;
02175 W[j][j] = 1.0/(std_ms*std_ms);
02176 j++;
02177 }
02178 }
02179 }
02180 }
02181
02182 if( rxData.m_pvt.isPositionConstrained )
02183 {
02184 if( j + 3 > n )
02185 return false;
02186
02187 W[j][j] = 1.0/(1.0e-10);
02188 j++;
02189 W[j][j] = 1.0/(1.0e-10);
02190 j++;
02191 W[j][j] = 1.0/(1.0e-10);
02192 j++;
02193 }
02194 else if( rxData.m_pvt.isHeightConstrained )
02195 {
02196 if( j + 1 > n )
02197 return false;
02198
02199 W[j][j] = 1.0/(1.0e-10);
02200 j++;
02201 }
02202
02203 return true;
02204 }
02205
02206
02207 bool GNSS_Estimator::DetermineMeasurementVarianceCovarianceMatrixForTheVelocitySolution_GPSL1(
02208 GNSS_RxData &rxData,
02209 const unsigned n,
02210 Matrix &R
02211 )
02212 {
02213 unsigned i = 0;
02214 unsigned j = 0;
02215 double std_ms = 0;
02216
02217
02218 if( R.GetNrRows() != n || R.GetNrCols() != n )
02219 {
02220 if( !R.Resize( n, n ) )
02221 return false;
02222 }
02223
02224 for( i = 0; i < rxData.m_nrValidObs; i++ )
02225 {
02226 if( rxData.m_ObsArray[i].flags.isActive )
02227 {
02228 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
02229 {
02230 if( rxData.m_ObsArray[i].flags.isDopplerUsedInSolution )
02231 {
02232
02233 if( j >= n )
02234 return false;
02235
02236
02237 if( rxData.m_ObsArray[i].stdev_doppler == 0.0 )
02238 return false;
02239
02240
02241 std_ms = rxData.m_ObsArray[i].stdev_doppler * GPS_WAVELENGTHL1;
02242
02243 R[j][j] = std_ms*std_ms;
02244 j++;
02245 }
02246 }
02247 }
02248 }
02249
02250 if( rxData.m_pvt.isPositionConstrained )
02251 {
02252 if( j + 3 > n )
02253 return false;
02254
02255 R[j][j] = 1.0e-10;
02256 j++;
02257 R[j][j] = 1.0e-10;
02258 j++;
02259 R[j][j] = 1.0e-10;
02260 j++;
02261 }
02262 else if( rxData.m_pvt.isHeightConstrained )
02263 {
02264 if( j + 1 > n )
02265 return false;
02266
02267 R[j][j] = 1.0e-10;
02268 j++;
02269 }
02270
02271 return true;
02272 }
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296 bool GNSS_Estimator::PerformGlobalTestAndTestForMeasurementFaults(
02297 GNSS_RxData &rxData,
02298 bool testPsrOrDoppler,
02299 Matrix& H,
02300 Matrix& Ht,
02301 Matrix& W,
02302 Matrix& R,
02303 Matrix& r,
02304 Matrix& P,
02305 const unsigned char n,
02306 const unsigned char u,
02307 double &avf,
02308 bool &isGlobalTestPassed,
02309 bool &hasRejectionOccurred,
02310 unsigned char &indexOfRejected
02311 )
02312 {
02313 double v = n-u;
02314
02315 unsigned i = 0;
02316 unsigned j = 0;
02317 unsigned indexvec[GNSS_RXDATA_NR_CHANNELS];
02318
02319 double rv = 0;
02320 double largest_rv = 0.0;
02321 unsigned char indexOfLargest = 0;
02322
02323 double chiSquaredValue = 0;
02324 double chiSquared005[31] = GNSS_CHISQUARE_00_5;
02325
02326
02327 isGlobalTestPassed = false;
02328 hasRejectionOccurred = false;
02329
02330 Matrix Cr;
02331 Matrix rT;
02332 Matrix r_standardized;
02333 Matrix tmpM;
02334
02335 PrintMatToDebug( "P", P );
02336
02337 i = static_cast<unsigned>(v);
02338 if( i == 0 )
02339 return true;
02340
02341 rT = r;
02342 if( !rT.Inplace_Transpose() )
02343 return false;
02344
02345
02346 tmpM = rT * W * r;
02347 avf = tmpM[0] / v;
02348
02349
02350 i = static_cast<unsigned>(v);
02351 if( i < 0 || i > 30 )
02352 return false;
02353 chiSquaredValue = chiSquared005[i];
02354 chiSquaredValue /= v;
02355
02356
02357 if( avf < chiSquaredValue )
02358 {
02359
02360 isGlobalTestPassed = true;
02361 return true;
02362 }
02363
02364
02365 i = static_cast<unsigned>(v);
02366 if( i <= 0 )
02367 {
02368 return true;
02369 }
02370
02371
02372
02373
02374
02375
02376
02377 j = 0;
02378 for( i = 0; i < rxData.m_nrValidObs; i++ )
02379 {
02380 if( rxData.m_ObsArray[i].flags.isActive )
02381 {
02382 if( rxData.m_ObsArray[i].system == GNSS_GPS && rxData.m_ObsArray[i].freqType == GNSS_GPSL1 )
02383 {
02384 if( testPsrOrDoppler )
02385 {
02386 if( rxData.m_ObsArray[i].flags.isPsrUsedInSolution )
02387 {
02388 indexvec[j] = i;
02389 j++;
02390 }
02391 }
02392 else
02393 {
02394 if( rxData.m_ObsArray[i].flags.isDopplerUsedInSolution )
02395 {
02396 indexvec[j] = i;
02397 j++;
02398 }
02399 }
02400 }
02401 }
02402 }
02403
02404
02405
02406 Cr = R - H * P * Ht;
02407
02408 PrintMatToDebug( "Cr", Cr );
02409
02410
02411
02412 for( i = 0; i < Cr.GetNrRows(); i++ )
02413 {
02414 if( Cr[i][i] <= 0.0 )
02415 {
02416 return false;
02417 }
02418 }
02419
02420
02421 if( !r_standardized.Resize( Cr.GetNrRows(), 1) )
02422 return false;
02423
02424
02425
02426 for( i = 0; i < Cr.GetNrRows(); i++ )
02427 {
02428 r_standardized[i] = r[i] / sqrt( Cr[i][i] );
02429
02430 rv = fabs( r_standardized[i] );
02431
02432
02433 if( rxData.m_pvt.isPositionConstrained )
02434 {
02435 if( i >= Cr.GetNrRows() -3 )
02436 continue;
02437 }
02438
02439 if( rv > largest_rv )
02440 {
02441 largest_rv = rv;
02442 indexOfLargest = i;
02443 }
02444 }
02445 indexOfLargest = indexvec[indexOfLargest];
02446
02447
02448 if( indexOfLargest >= rxData.m_nrValidObs )
02449 return false;
02450
02451 PrintMatToDebug( "r", r );
02452 PrintMatToDebug( "r_standardized", r_standardized );
02453
02454
02455 if( largest_rv > 4.57 )
02456 {
02457
02458 hasRejectionOccurred = true;
02459
02460 if( testPsrOrDoppler )
02461 rxData.m_ObsArray[indexOfLargest].flags.isNotPsrRejected = 0;
02462 else
02463 rxData.m_ObsArray[indexOfLargest].flags.isNotDopplerRejected = 0;
02464 }
02465
02466 return true;
02467 }
02468
02469
02470 bool GNSS_Estimator::ComputeTransitionMatrix_8StatePVGM(
02471 const double dT,
02472 Matrix &T
02473 )
02474 {
02475 const double betaVn = 1.0/m_KF.alphaVn;
02476 const double betaVe = 1.0/m_KF.alphaVe;
02477 const double betaVup = 1.0/m_KF.alphaVup;
02478 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02479
02480 double eVn = 0;
02481 double eVe = 0;
02482 double eVup = 0;
02483 double eClkDrift = 0;
02484
02485
02486 if( T.GetNrRows() != 8 || T.GetNrCols() != 8 )
02487 {
02488 if( !T.Resize(8,8) )
02489 return false;
02490 }
02491
02492 eVn = exp( -betaVn * dT );
02493 eVe = exp( -betaVe * dT );
02494 eVup = exp( -betaVup * dT );
02495
02496 eClkDrift = exp( -betaClkDrift * dT );
02497
02498 T.Zero();
02499
02500 T[0][0] = 1.0;
02501 T[0][3] = (1.0 - eVn) / betaVn;
02502
02503 T[1][1] = 1.0;
02504 T[1][4] = (1.0 - eVe) / betaVe;
02505
02506 T[2][2] = 1.0;
02507 T[2][5] = (1.0 - eVup) / betaVup;
02508
02509 T[3][3] = eVn;
02510 T[4][4] = eVe;
02511 T[5][5] = eVup;
02512
02513 T[6][6] = 1.0;
02514 T[6][7] = (1.0 - eClkDrift) / betaClkDrift;
02515
02516 T[7][7] = eClkDrift;
02517
02518 return true;
02519 }
02520
02521 bool GNSS_Estimator::ComputeTransitionMatrix_8StatePVGM_Float(
02522 const double dT,
02523 Matrix &T
02524 )
02525 {
02526 const double betaVn = 1.0/m_KF.alphaVn;
02527 const double betaVe = 1.0/m_KF.alphaVe;
02528 const double betaVup = 1.0/m_KF.alphaVup;
02529 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02530
02531 double eVn = 0;
02532 double eVe = 0;
02533 double eVup = 0;
02534 double eClkDrift = 0;
02535 const unsigned int u = 8 + static_cast<unsigned int>(m_ActiveAmbiguitiesList.size());
02536
02537 T.Identity( u );
02538
02539 eVn = exp( -betaVn * dT );
02540 eVe = exp( -betaVe * dT );
02541 eVup = exp( -betaVup * dT );
02542
02543 eClkDrift = exp( -betaClkDrift * dT );
02544
02545 T[0][0] = 1.0;
02546 T[0][3] = (1.0 - eVn) / betaVn;
02547
02548 T[1][1] = 1.0;
02549 T[1][4] = (1.0 - eVe) / betaVe;
02550
02551 T[2][2] = 1.0;
02552 T[2][5] = (1.0 - eVup) / betaVup;
02553
02554 T[3][3] = eVn;
02555 T[4][4] = eVe;
02556 T[5][5] = eVup;
02557
02558 T[6][6] = 1.0;
02559 T[6][7] = (1.0 - eClkDrift) / betaClkDrift;
02560
02561 T[7][7] = eClkDrift;
02562
02563 return true;
02564 }
02565
02566 bool GNSS_Estimator::ComputeTransitionMatrix_6StatePVGM_Float(
02567 const double dT,
02568 Matrix &T
02569 )
02570 {
02571 const double betaVn = 1.0/m_KF.alphaVn;
02572 const double betaVe = 1.0/m_KF.alphaVe;
02573 const double betaVup = 1.0/m_KF.alphaVup;
02574 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02575
02576
02577 double eVn = 0;
02578 double eVe = 0;
02579 double eVup = 0;
02580
02581
02582
02583 const unsigned int u = 6;
02584
02585 T.Redim(u,u);
02586
02587 eVn = exp( -betaVn * dT );
02588 eVe = exp( -betaVe * dT );
02589 eVup = exp( -betaVup * dT );
02590
02591
02592
02593 T[0][0] = 1.0;
02594 T[0][3] = (1.0 - eVn) / betaVn;
02595
02596 T[1][1] = 1.0;
02597 T[1][4] = (1.0 - eVe) / betaVe;
02598
02599 T[2][2] = 1.0;
02600 T[2][5] = (1.0 - eVup) / betaVup;
02601
02602 T[3][3] = eVn;
02603 T[4][4] = eVe;
02604 T[5][5] = eVup;
02605
02606
02607
02608
02609
02610
02611 return true;
02612 }
02613
02614
02615
02616 bool GNSS_Estimator::ComputeProcessNoiseMatrix_8StatePVGM(
02617 const double dT,
02618 Matrix &Q
02619 )
02620 {
02621 const double betaVn = 1.0/m_KF.alphaVn;
02622 const double betaVe = 1.0/m_KF.alphaVe;
02623 const double betaVup = 1.0/m_KF.alphaVup;
02624 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02625
02626 const double qVn = 2 * m_KF.sigmaVn * m_KF.sigmaVn * betaVn;
02627 const double qVe = 2 * m_KF.sigmaVe * m_KF.sigmaVe * betaVe;
02628 const double qVup = 2 * m_KF.sigmaVup * m_KF.sigmaVup * betaVup;
02629 const double qClkDrift = 2 * m_KF.sigmaClkDrift * m_KF.sigmaClkDrift * betaClkDrift;
02630
02631 double eVn = 0;
02632 double eVe = 0;
02633 double eVup = 0;
02634 double eClkDrift = 0;
02635 double eVn2 = 0;
02636 double eVe2 = 0;
02637 double eVup2 = 0;
02638 double eClkDrift2 = 0;
02639
02640 const unsigned int u = 8;
02641
02642 if( Q.nrows() != u )
02643 {
02644 if( !Q.Resize( u, u ) )
02645 {
02646 return false;
02647 }
02648 }
02649
02650
02651 eVn = exp( -betaVn * dT );
02652 eVe = exp( -betaVe * dT );
02653 eVup = exp( -betaVup * dT );
02654 eClkDrift = exp( -betaClkDrift * dT );
02655
02656 eVn2 = exp( -2.0 * betaVn * dT );
02657 eVe2 = exp( -2.0 * betaVe * dT );
02658 eVup2 = exp( -2.0 * betaVup * dT );
02659 eClkDrift2 = exp( -2.0 * betaClkDrift * dT );
02660
02661 Q[0][0] = qVn / (betaVn*betaVn);
02662 Q[0][0] *= dT - 2.0*(1.0 - eVn)/(betaVn) + (1.0 - eVn2)/(2.0*betaVn);
02663
02664 Q[1][1] = qVe / (betaVe*betaVe);
02665 Q[1][1] *= dT - 2.0*(1.0 - eVe)/(betaVe) + (1.0 - eVe2)/(2.0*betaVe);
02666
02667 Q[2][2] = qVn / (betaVup*betaVup);
02668 Q[2][2] *= dT - 2.0*(1.0 - eVup)/(betaVup) + (1.0 - eVup2)/(2.0*betaVup);
02669
02670 Q[3][3] = qVn * (1.0 - eVn2) / (2.0*betaVn);
02671
02672 Q[4][4] = qVe * (1.0 - eVe2) / (2.0*betaVe);
02673
02674 Q[5][5] = qVup * (1.0 - eVup2) / (2.0*betaVup);
02675
02676 Q[6][6] = qClkDrift / (betaClkDrift*betaClkDrift);
02677 Q[6][6] *= dT - 2.0*(1.0 - eClkDrift)/(betaClkDrift) + (1.0 - eClkDrift2)/(2.0*betaClkDrift);
02678
02679 Q[7][7] = qClkDrift * (1.0 - eClkDrift2) / (2.0*betaClkDrift);
02680
02681 Q[0][3] = qVn / betaVn;
02682 Q[0][3] *= (1.0 - eVn)/betaVn - (1.0 - eVn2)/(2.0*betaVn);
02683 Q[3][0] = Q[0][3];
02684
02685 Q[1][4] = qVe / betaVe;
02686 Q[1][4] *= (1.0 - eVe)/betaVe - (1.0 - eVe2)/(2.0*betaVe);
02687 Q[4][1] = Q[1][4];
02688
02689 Q[2][5] = qVup / betaVup;
02690 Q[2][5] *= (1.0 - eVup)/betaVup - (1.0 - eVup2)/(2.0*betaVup);
02691 Q[5][2] = Q[2][5];
02692
02693 Q[6][7] = qClkDrift / betaClkDrift;
02694 Q[6][7] *= (1.0 - eClkDrift)/betaClkDrift - (1.0 - eClkDrift2)/(2.0*betaClkDrift);
02695 Q[7][6] = Q[6][7];
02696
02697 return true;
02698 }
02699
02700
02701 bool GNSS_Estimator::ComputeProcessNoiseMatrix_8StatePVGM_Float(
02702 const double dT,
02703 Matrix &Q
02704 )
02705 {
02706 const double betaVn = 1.0/m_KF.alphaVn;
02707 const double betaVe = 1.0/m_KF.alphaVe;
02708 const double betaVup = 1.0/m_KF.alphaVup;
02709 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02710
02711 const double qVn = 2 * m_KF.sigmaVn * m_KF.sigmaVn * betaVn;
02712 const double qVe = 2 * m_KF.sigmaVe * m_KF.sigmaVe * betaVe;
02713 const double qVup = 2 * m_KF.sigmaVup * m_KF.sigmaVup * betaVup;
02714 const double qClkDrift = 2 * m_KF.sigmaClkDrift * m_KF.sigmaClkDrift * betaClkDrift;
02715
02716 double eVn = 0;
02717 double eVe = 0;
02718 double eVup = 0;
02719 double eClkDrift = 0;
02720 double eVn2 = 0;
02721 double eVe2 = 0;
02722 double eVup2 = 0;
02723 double eClkDrift2 = 0;
02724
02725 const unsigned int u = 8 + static_cast<unsigned int>(m_ActiveAmbiguitiesList.size());
02726
02727 if( Q.nrows() != u )
02728 {
02729 if( !Q.Resize( u, u ) )
02730 {
02731 return false;
02732 }
02733 }
02734
02735 eVn = exp( -betaVn * dT );
02736 eVe = exp( -betaVe * dT );
02737 eVup = exp( -betaVup * dT );
02738 eClkDrift = exp( -betaClkDrift * dT );
02739
02740 eVn2 = exp( -2.0 * betaVn * dT );
02741 eVe2 = exp( -2.0 * betaVe * dT );
02742 eVup2 = exp( -2.0 * betaVup * dT );
02743 eClkDrift2 = exp( -2.0 * betaClkDrift * dT );
02744
02745 Q[0][0] = qVn / (betaVn*betaVn);
02746 Q[0][0] *= dT - 2.0*(1.0 - eVn)/(betaVn) + (1.0 - eVn2)/(2.0*betaVn);
02747
02748 Q[1][1] = qVe / (betaVe*betaVe);
02749 Q[1][1] *= dT - 2.0*(1.0 - eVe)/(betaVe) + (1.0 - eVe2)/(2.0*betaVe);
02750
02751 Q[2][2] = qVn / (betaVup*betaVup);
02752 Q[2][2] *= dT - 2.0*(1.0 - eVup)/(betaVup) + (1.0 - eVup2)/(2.0*betaVup);
02753
02754 Q[3][3] = qVn * (1.0 - eVn2) / (2.0*betaVn);
02755
02756 Q[4][4] = qVe * (1.0 - eVe2) / (2.0*betaVe);
02757
02758 Q[5][5] = qVup * (1.0 - eVup2) / (2.0*betaVup);
02759
02760 Q[6][6] = qClkDrift / (betaClkDrift*betaClkDrift);
02761 Q[6][6] *= dT - 2.0*(1.0 - eClkDrift)/(betaClkDrift) + (1.0 - eClkDrift2)/(2.0*betaClkDrift);
02762
02763 Q[7][7] = qClkDrift * (1.0 - eClkDrift2) / (2.0*betaClkDrift);
02764
02765 Q[0][3] = qVn / betaVn;
02766 Q[0][3] *= (1.0 - eVn)/betaVn - (1.0 - eVn2)/(2.0*betaVn);
02767 Q[3][0] = Q[0][3];
02768
02769 Q[1][4] = qVe / betaVe;
02770 Q[1][4] *= (1.0 - eVe)/betaVe - (1.0 - eVe2)/(2.0*betaVe);
02771 Q[4][1] = Q[1][4];
02772
02773 Q[2][5] = qVup / betaVup;
02774 Q[2][5] *= (1.0 - eVup)/betaVup - (1.0 - eVup2)/(2.0*betaVup);
02775 Q[5][2] = Q[2][5];
02776
02777 Q[6][7] = qClkDrift / betaClkDrift;
02778 Q[6][7] *= (1.0 - eClkDrift)/betaClkDrift - (1.0 - eClkDrift2)/(2.0*betaClkDrift);
02779 Q[7][6] = Q[6][7];
02780
02781 return true;
02782 }
02783
02784 bool GNSS_Estimator::ComputeProcessNoiseMatrix_6StatePVGM_Float(
02785 const double dT,
02786 Matrix &Q
02787 )
02788 {
02789 const double betaVn = 1.0/m_KF.alphaVn;
02790 const double betaVe = 1.0/m_KF.alphaVe;
02791 const double betaVup = 1.0/m_KF.alphaVup;
02792 const double betaClkDrift = 1.0/m_KF.alphaClkDrift;
02793
02794 const double qVn = 2 * m_KF.sigmaVn * m_KF.sigmaVn * betaVn;
02795 const double qVe = 2 * m_KF.sigmaVe * m_KF.sigmaVe * betaVe;
02796 const double qVup = 2 * m_KF.sigmaVup * m_KF.sigmaVup * betaVup;
02797 const double qClkDrift = 2 * m_KF.sigmaClkDrift * m_KF.sigmaClkDrift * betaClkDrift;
02798
02799
02800 double eVn = 0;
02801 double eVe = 0;
02802 double eVup = 0;
02803
02804 double eVn2 = 0;
02805 double eVe2 = 0;
02806 double eVup2 = 0;
02807
02808
02809
02810 const unsigned int u = 6;
02811
02812 if( Q.nrows() != u )
02813 {
02814 if( !Q.Resize( u, u ) )
02815 {
02816 return false;
02817 }
02818 }
02819
02820 eVn = exp( -betaVn * dT );
02821 eVe = exp( -betaVe * dT );
02822 eVup = exp( -betaVup * dT );
02823
02824
02825 eVn2 = exp( -2.0 * betaVn * dT );
02826 eVe2 = exp( -2.0 * betaVe * dT );
02827 eVup2 = exp( -2.0 * betaVup * dT );
02828
02829
02830 Q[0][0] = qVn / (betaVn*betaVn);
02831 Q[0][0] *= dT - 2.0*(1.0 - eVn)/(betaVn) + (1.0 - eVn2)/(2.0*betaVn);
02832
02833 Q[1][1] = qVe / (betaVe*betaVe);
02834 Q[1][1] *= dT - 2.0*(1.0 - eVe)/(betaVe) + (1.0 - eVe2)/(2.0*betaVe);
02835
02836 Q[2][2] = qVn / (betaVup*betaVup);
02837 Q[2][2] *= dT - 2.0*(1.0 - eVup)/(betaVup) + (1.0 - eVup2)/(2.0*betaVup);
02838
02839 Q[3][3] = qVn * (1.0 - eVn2) / (2.0*betaVn);
02840
02841 Q[4][4] = qVe * (1.0 - eVe2) / (2.0*betaVe);
02842
02843 Q[5][5] = qVup * (1.0 - eVup2) / (2.0*betaVup);
02844
02845
02846
02847
02848
02849
02850
02851
02852 Q[0][3] = qVn / betaVn;
02853 Q[0][3] *= (1.0 - eVn)/betaVn - (1.0 - eVn2)/(2.0*betaVn);
02854 Q[3][0] = Q[0][3];
02855
02856 Q[1][4] = qVe / betaVe;
02857 Q[1][4] *= (1.0 - eVe)/betaVe - (1.0 - eVe2)/(2.0*betaVe);
02858 Q[4][1] = Q[1][4];
02859
02860 Q[2][5] = qVup / betaVup;
02861 Q[2][5] *= (1.0 - eVup)/betaVup - (1.0 - eVup2)/(2.0*betaVup);
02862 Q[5][2] = Q[2][5];
02863
02864
02865
02866
02867
02868 return true;
02869 }
02870
02871
02872
02873 bool GNSS_Estimator::PredictAhead_8StatePVGM(
02874 GNSS_RxData &rxData,
02875 const double dT,
02876 Matrix &T,
02877 Matrix &Q,
02878 Matrix &P
02879 )
02880 {
02881 double M = 0;
02882 double N = 0;
02883 bool result = false;
02884 Matrix tmpMat;
02885 double lat = 0;
02886 double h = 0;
02887
02888 GEODESY_ComputeMeridianRadiusOfCurvature(
02889 GEODESY_REFERENCE_ELLIPSE_WGS84,
02890 rxData.m_pvt.latitude,
02891 &M );
02892
02893 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
02894 GEODESY_REFERENCE_ELLIPSE_WGS84,
02895 rxData.m_pvt.latitude,
02896 &N );
02897
02898
02899 result = ComputeTransitionMatrix_8StatePVGM( dT, T );
02900 if( result == false )
02901 return false;
02902
02903
02904 result = ComputeProcessNoiseMatrix_8StatePVGM( dT, Q );
02905 if( result == false )
02906 return false;
02907
02908
02909
02910
02911
02912
02913 lat = rxData.m_pvt.latitude;
02914 h = rxData.m_pvt.height;
02915
02916 rxData.m_pvt.latitude += T[0][3] * rxData.m_pvt.vn / (M+h);
02917 rxData.m_pvt.longitude += T[1][4] * rxData.m_pvt.ve / ((N+h)*cos(lat));
02918 rxData.m_pvt.height += T[2][5] * rxData.m_pvt.vup;
02919
02920 rxData.m_pvt.vn *= T[3][3];
02921 rxData.m_pvt.ve *= T[4][4];
02922 rxData.m_pvt.vup *= T[5][5];
02923
02924 rxData.m_pvt.clockOffset += T[6][7] * rxData.m_pvt.clockDrift;
02925 rxData.m_pvt.clockDrift *= T[7][7];
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937 tmpMat = T;
02938 if( !tmpMat.Inplace_Transpose() )
02939 return false;
02940
02941 if( !P.Inplace_PreMultiply( T ) )
02942 return false;
02943
02944 if( !P.Inplace_PostMultiply( tmpMat ) )
02945 return false;
02946
02947 if( !P.Inplace_Add( Q ) )
02948 return false;
02949
02950
02951
02952 return true;
02953 }
02954
02955
02956 bool GNSS_Estimator::PredictAhead_8StatePVGM_Float(
02957 GNSS_RxData &rxData,
02958 const double dT,
02959 Matrix &T,
02960 Matrix &Q,
02961 Matrix &P
02962 )
02963 {
02964 double M = 0;
02965 double N = 0;
02966 bool result = false;
02967 Matrix tmpMat;
02968 double lat = 0;
02969 double h = 0;
02970
02971 GEODESY_ComputeMeridianRadiusOfCurvature(
02972 GEODESY_REFERENCE_ELLIPSE_WGS84,
02973 rxData.m_pvt.latitude,
02974 &M );
02975
02976 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
02977 GEODESY_REFERENCE_ELLIPSE_WGS84,
02978 rxData.m_pvt.latitude,
02979 &N );
02980
02981
02982 result = ComputeTransitionMatrix_8StatePVGM_Float( dT, T );
02983 if( result == false )
02984 return false;
02985
02986 PrintMatToDebug( "T", T );
02987
02988
02989 result = ComputeProcessNoiseMatrix_8StatePVGM_Float( dT, Q );
02990 if( result == false )
02991 return false;
02992
02993 PrintMatToDebug( "Q", Q );
02994
02995
02996
02997
02998
02999 lat = rxData.m_pvt.latitude;
03000 h = rxData.m_pvt.height;
03001
03002 rxData.m_pvt.latitude += T[0][3] * rxData.m_pvt.vn / (M+h);
03003 rxData.m_pvt.longitude += T[1][4] * rxData.m_pvt.ve / ((N+h)*cos(lat));
03004 rxData.m_pvt.height += T[2][5] * rxData.m_pvt.vup;
03005
03006 rxData.m_pvt.vn *= T[3][3];
03007 rxData.m_pvt.ve *= T[4][4];
03008 rxData.m_pvt.vup *= T[5][5];
03009
03010 rxData.m_pvt.clockOffset += T[6][7] * rxData.m_pvt.clockDrift;
03011 rxData.m_pvt.clockDrift *= T[7][7];
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025 tmpMat = T;
03026 if( !tmpMat.Inplace_Transpose() )
03027 return false;
03028
03029 if( !P.Inplace_PreMultiply( T ) )
03030 return false;
03031
03032 if( !P.Inplace_PostMultiply( tmpMat ) )
03033 return false;
03034
03035 if( !P.Inplace_Add( Q ) )
03036 return false;
03037
03038
03039
03040 result = rxData.UpdatePositionAndRxClock(
03041 rxData.m_pvt.latitude,
03042 rxData.m_pvt.longitude,
03043 rxData.m_pvt.height,
03044 rxData.m_pvt.clockOffset,
03045 sqrt( P[0][0] ),
03046 sqrt( P[1][1] ),
03047 sqrt( P[2][2] ),
03048 sqrt( P[6][6] )
03049 );
03050 if( !result )
03051 return false;
03052
03053 result = rxData.UpdateVelocityAndClockDrift(
03054 rxData.m_pvt.vn,
03055 rxData.m_pvt.ve,
03056 rxData.m_pvt.vup,
03057 rxData.m_pvt.clockDrift,
03058 sqrt( P[3][3] ),
03059 sqrt( P[4][4] ),
03060 sqrt( P[5][5] ),
03061 sqrt( P[7][7] )
03062 );
03063 if( !result )
03064 return false;
03065
03066 PrintMatToDebug( "P", P );
03067
03068 return true;
03069 }
03070
03071 bool GNSS_Estimator::PredictAhead_6StatePVGM_Float(
03072 GNSS_RxData &rxData,
03073 const double dT,
03074 Matrix &T,
03075 Matrix &Q,
03076 Matrix &P
03077 )
03078 {
03079 unsigned i = 0;
03080 unsigned j = 0;
03081 double M = 0;
03082 double N = 0;
03083 bool result = false;
03084 Matrix tmpMat;
03085 double lat = 0;
03086 double h = 0;
03087
03088 GEODESY_ComputeMeridianRadiusOfCurvature(
03089 GEODESY_REFERENCE_ELLIPSE_WGS84,
03090 rxData.m_pvt.latitude,
03091 &M );
03092
03093 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
03094 GEODESY_REFERENCE_ELLIPSE_WGS84,
03095 rxData.m_pvt.latitude,
03096 &N );
03097
03098
03099 result = ComputeTransitionMatrix_6StatePVGM_Float( dT, T );
03100 if( result == false )
03101 return false;
03102
03103 PrintMatToDebug( "T", T );
03104
03105
03106 result = ComputeProcessNoiseMatrix_6StatePVGM_Float( dT, Q );
03107 if( result == false )
03108 return false;
03109
03110 PrintMatToDebug( "Q", Q );
03111
03112
03113
03114
03115
03116 lat = rxData.m_pvt.latitude;
03117 h = rxData.m_pvt.height;
03118
03119 rxData.m_pvt.latitude += T[0][3] * rxData.m_pvt.vn / (M+h);
03120 rxData.m_pvt.longitude += T[1][4] * rxData.m_pvt.ve / ((N+h)*cos(lat));
03121 rxData.m_pvt.height += T[2][5] * rxData.m_pvt.vup;
03122
03123 rxData.m_pvt.vn *= T[3][3];
03124 rxData.m_pvt.ve *= T[4][4];
03125 rxData.m_pvt.vup *= T[5][5];
03126
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136
03137
03138 if( !T.Redim( P.nrows(), P.ncols() ) )
03139 return false;
03140
03141 for( i = 6; i < T.nrows(); i++ )
03142 {
03143 for( j = 6; j < T.ncols(); j++ )
03144 {
03145 T[i][j] = 1.0;
03146 }
03147 }
03148
03149 tmpMat = T;
03150 if( !tmpMat.Inplace_Transpose() )
03151 return false;
03152
03153 if( !P.Inplace_PreMultiply( T ) )
03154 return false;
03155
03156 if( !P.Inplace_PostMultiply( tmpMat ) )
03157 return false;
03158
03159 if( !Q.Redim( P.nrows(), P.ncols() ) )
03160 return false;
03161
03162 if( !P.Inplace_Add( Q ) )
03163 return false;
03164
03165
03166
03167 PrintMatToDebug( "P", P );
03168
03169 return true;
03170 }
03171
03172
03173
03174
03175
03176
03177 bool GNSS_Estimator::InitializeStateVarianceCovariance_8StatePVGM(
03178 const double std_lat,
03179 const double std_lon,
03180 const double std_hgt,
03181 const double std_vn,
03182 const double std_ve,
03183 const double std_vup,
03184 const double std_clk,
03185 const double std_clkdrift,
03186 Matrix &P
03187 )
03188 {
03189 if( P.GetNrRows() != 8 || P.GetNrCols() != 8 )
03190 {
03191 if( !P.Resize( 8, 8 ) )
03192 {
03193 return false;
03194 }
03195 }
03196
03197 P[0][0] = std_lat*std_lat;
03198 P[1][1] = std_lon*std_lon;
03199 P[2][2] = std_hgt*std_hgt;
03200 P[3][3] = std_vn*std_vn;
03201 P[4][4] = std_ve*std_ve;
03202 P[5][5] = std_vup*std_vup;
03203 P[6][6] = std_clk*std_clk;
03204 P[7][7] = std_clkdrift*std_clkdrift;
03205
03206 PrintMatToDebug( "P", P );
03207
03208 return true;
03209 }
03210
03211 bool GNSS_Estimator::InitializeStateVarianceCovariance_6StatePVGM(
03212 const double std_lat,
03213 const double std_lon,
03214 const double std_hgt,
03215 const double std_vn,
03216 const double std_ve,
03217 const double std_vup,
03218 Matrix &P
03219 )
03220 {
03221 if( P.GetNrRows() != 6 || P.GetNrCols() != 6 )
03222 {
03223 if( !P.Resize( 6, 6 ) )
03224 {
03225 return false;
03226 }
03227 }
03228
03229 P[0][0] = std_lat*std_lat;
03230 P[1][1] = std_lon*std_lon;
03231 P[2][2] = std_hgt*std_hgt;
03232 P[3][3] = std_vn*std_vn;
03233 P[4][4] = std_ve*std_ve;
03234 P[5][5] = std_vup*std_vup;
03235
03236 PrintMatToDebug( "P", P );
03237
03238 return true;
03239 }
03240
03241
03242 bool GNSS_Estimator::Kalman_Update_8StatePVGM(
03243 GNSS_RxData *rxData,
03244 GNSS_RxData *rxBaseData,
03245 Matrix &P
03246 )
03247 {
03248 bool result = false;
03249 unsigned i = 0;
03250 unsigned j = 0;
03251 unsigned n = 0;
03252 unsigned nrP = 0;
03253 unsigned nrP_base = 0;
03254 unsigned nrD = 0;
03255 unsigned nrD_base = 0;
03256 unsigned nrValidEph = 0;
03257 unsigned nrDifferentialPsr = 0;
03258 unsigned nrDifferentialDoppler = 0;
03259 bool isDifferential = false;
03260
03261 double lat = 0;
03262 double lon = 0;
03263 double hgt = 0;
03264 double clk = 0;
03265 double vn = 0;
03266 double ve = 0;
03267 double vup = 0;
03268 double clkdrift = 0;
03269 double M = 0;
03270 double N = 0;
03271
03272 Matrix H_p;
03273 Matrix H_v;
03274 Matrix H;
03275 Matrix Ht;
03276 Matrix R_p;
03277 Matrix R_v;
03278 Matrix R;
03279 Matrix w_p;
03280 Matrix w_v;
03281 Matrix w;
03282 Matrix K;
03283 Matrix tmpMat;
03284 Matrix tmpMatP;
03285 Matrix dx(8);
03286 Matrix I;
03287
03288
03289 dx.Zero();
03290
03291
03292 rxData->m_prev_pvt = rxData->m_pvt;
03293
03294 lat = rxData->m_pvt.latitude;
03295 lon = rxData->m_pvt.longitude;
03296 hgt = rxData->m_pvt.height;
03297 clk = rxData->m_pvt.clockOffset;
03298 vn = rxData->m_pvt.vn;
03299 ve = rxData->m_pvt.ve;
03300 vup = rxData->m_pvt.vup;
03301 clkdrift = rxData->m_pvt.clockDrift;
03302
03303
03304 if( rxBaseData != NULL )
03305 isDifferential = true;
03306
03307 #ifdef CONSTRAINPOS
03308 rxData->m_pvt.isPositionConstrained = 1;
03309 #else
03310 rxData->m_pvt.isPositionConstrained = 0;
03311 #endif
03312
03313
03314
03315
03316
03317
03318 result = UpdateTime( *rxData );
03319 if( !result )
03320 return false;
03321 if( isDifferential )
03322 {
03323 result = UpdateTime( *rxBaseData );
03324 if( !result )
03325 return false;
03326 }
03327
03328 result = DetermineSatellitePVT_GPSL1( rxData, rxBaseData, nrValidEph );
03329 if( !result )
03330 return false;
03331
03332
03333 result = DetermineAtmosphericCorrections_GPSL1( *rxData );
03334 if( !result )
03335 return false;
03336 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxData, nrP );
03337 if( !result )
03338 return false;
03339 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxData, nrD );
03340 if( !result )
03341 return false;
03342
03343
03344 if( isDifferential )
03345 {
03346 result = DetermineAtmosphericCorrections_GPSL1( *rxBaseData );
03347 if( !result )
03348 return false;
03349 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxBaseData, nrP_base );
03350 if( !result )
03351 return false;
03352 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxBaseData, nrD_base );
03353 if( !result )
03354 return false;
03355
03356
03357 result = DetermineBetweenReceiverDifferentialIndex(
03358 rxData,
03359 rxBaseData,
03360 true
03361 );
03362 if( !result )
03363 return false;
03364
03365 nrDifferentialPsr = 0;
03366 for( i = 0; i < rxData->m_nrValidObs; i++ )
03367 {
03368 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
03369 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
03370 rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
03371 {
03372 nrDifferentialPsr++;
03373 }
03374 }
03375
03376 #ifdef CONSTRAINPOS
03377 nrP = nrDifferentialPsr+3;
03378 #else
03379 nrP = nrDifferentialPsr;
03380 #endif
03381
03382 nrDifferentialDoppler = 0;
03383 for( i = 0; i < rxData->m_nrValidObs; i++ )
03384 {
03385 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
03386 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
03387 rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
03388 {
03389 nrDifferentialDoppler++;
03390 }
03391 }
03392
03393 #ifdef CONSTRAINPOS
03394 nrD = nrDifferentialPsr+3;
03395 #else
03396 nrD = nrDifferentialPsr;
03397 #endif
03398 }
03399
03400 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
03401 *rxData,
03402 nrP,
03403 H_p );
03404 if( !result )
03405 return false;
03406
03407 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
03408 *rxData,
03409 nrD,
03410 H_v );
03411 if( !result )
03412 return false;
03413
03414
03415 result = DetermineMeasurementVarianceCovarianceMatrixForThePositionSolution_GPSL1(
03416 *rxData,
03417 nrP,
03418 R_p );
03419 if( !result )
03420 return false;
03421
03422
03423 result = DetermineMeasurementVarianceCovarianceMatrixForTheVelocitySolution_GPSL1(
03424 *rxData,
03425 nrD,
03426 R_v );
03427 if( !result )
03428 return false;
03429
03430
03431 result = DeterminePseudorangeMisclosures_GPSL1(
03432 rxData,
03433 rxBaseData,
03434 nrP,
03435 w_p );
03436 if( !result )
03437 return false;
03438
03439 result = DetermineDopplerMisclosures_GPSL1(
03440 rxData,
03441 rxBaseData,
03442 nrD,
03443 w_v );
03444 if( !result )
03445 return false;
03446
03447
03448 n = H_p.GetNrRows() + H_v.GetNrRows();
03449
03450 result = H.Resize( n, 8 );
03451 if( !result )
03452 return false;
03453
03454 for( i = 0; i < n; i++ )
03455 {
03456 if( i < nrP )
03457 {
03458 for( j = 0; j < 3; j++ )
03459 H[i][j] = H_p[i][j];
03460 #ifdef CONSTRAINPOS
03461 if( i < nrP-3 )
03462 H[i][6] = 1.0;
03463 #else
03464 H[i][6] = 1.0;
03465 #endif
03466 }
03467 else
03468 {
03469 for( j = 0; j < 3; j++ )
03470 H[i][j+3] = H_v[i-nrP][j];
03471 #ifdef CONSTRAINPOS
03472 if( i < n-3 )
03473 H[i][7] = 1.0;
03474 #else
03475 H[i][7] = 1.0;
03476 #endif
03477 }
03478 }
03479 PrintMatToDebug( "H", H );
03480
03481
03482 result = R.Resize( n, n );
03483 if( !result )
03484 return false;
03485
03486
03487 for( i = 0; i < n; i++ )
03488 {
03489 if( i < nrP )
03490 {
03491 for( j = 0; j < nrP; j++ )
03492 R[i][j] = R_p[i][j];
03493 }
03494 else
03495 {
03496 for( j = 0; j < nrD; j++ )
03497 R[i][j+nrD] = R_v[i-nrP][j];
03498 }
03499 }
03500 PrintMatToDebug( "R", R );
03501
03502
03503
03504 result = w.Resize( n, 1 );
03505 if( !result )
03506 return false;
03507 for( i = 0; i < n; i++ )
03508 {
03509 if( i < nrP )
03510 {
03511 w[i] = w_p[i];
03512 }
03513 else
03514 {
03515 w[i] = w_v[i-nrP];
03516 }
03517 }
03518
03519
03520
03521 Ht = H;
03522 result = Ht.Inplace_Transpose();
03523 if( !result )
03524 return false;
03525
03526
03527 PrintMatToDebug( "H", H );
03528 PrintMatToDebug( "R", R );
03529 PrintMatToDebug( "w", w );
03530 PrintMatToDebug( "P", P );
03531
03532
03533
03534
03535 tmpMat = H*P*Ht + R;
03536 result = tmpMat.Inplace_Invert();
03537 if( !result )
03538 return false;
03539 K = P*Ht*tmpMat;
03540
03541
03542
03543 dx = K*w;
03544
03545
03546
03547
03548 result = I.Resize( 8, 8 );
03549 if( !result )
03550 return false;
03551 result = I.Identity();
03552 if( !result )
03553 return false;
03554
03555 P = (I - K * H)*P;
03556
03557 PrintMatToDebug( "dx", dx );
03558 PrintMatToDebug( "P", P );
03559 PrintMatToDebug( "K", K );
03560
03561
03562
03563
03564 hgt += dx[2];
03565 clk += dx[6];
03566
03567
03568 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
03569 GEODESY_REFERENCE_ELLIPSE_WGS84,
03570 lat,
03571 &N );
03572 GEODESY_ComputeMeridianRadiusOfCurvature(
03573 GEODESY_REFERENCE_ELLIPSE_WGS84,
03574 lat,
03575 &M );
03576
03577 lat += dx[0] / ( M + hgt );
03578 lon += dx[1] / (( N + hgt )*cos(lat));
03579
03580 result = rxData->UpdatePositionAndRxClock(
03581 lat,
03582 lon,
03583 hgt,
03584 clk,
03585 sqrt(P[0][0]),
03586 sqrt(P[1][1]),
03587 sqrt(P[2][2]),
03588 sqrt(P[6][6])
03589 );
03590 if( !result )
03591 return false;
03592
03593
03594
03595 vn += dx[3];
03596 ve += dx[4];
03597 vup += dx[5];
03598 clkdrift += dx[7];
03599
03600 result = rxData->UpdateVelocityAndClockDrift(
03601 vn,
03602 ve,
03603 vup,
03604 clkdrift,
03605 sqrt(P[3][3]),
03606 sqrt(P[4][4]),
03607 sqrt(P[5][5]),
03608 sqrt(P[7][7]) );
03609 if( !result )
03610 return false;
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630
03631
03632 return true;
03633 }
03634
03635
03636
03637 bool GNSS_Estimator::Kalman_Update_6StatePVGM_FloatSolution(
03638 GNSS_RxData *rxData,
03639 GNSS_RxData *rxBaseData,
03640 Matrix &P
03641 )
03642 {
03643 bool result = false;
03644 unsigned index = 0;
03645 unsigned i = 0;
03646 unsigned j = 0;
03647 unsigned k = 0;
03648 unsigned m = 0;
03649 unsigned n = 0;
03650 unsigned nrP = 0;
03651 unsigned nrP_base = 0;
03652 unsigned nrD = 0;
03653 unsigned nrD_base = 0;
03654 unsigned nrValidEph = 0;
03655 unsigned nrUsableAdr = 0;
03656 unsigned nrUsableAdr_base = 0;
03657 unsigned nrDifferentialPsr = 0;
03658 unsigned nrDifferentialDoppler = 0;
03659 unsigned nrDifferentialAdr = 0;
03660 unsigned nDD = 0;
03661 unsigned nrPDD = 0;
03662 unsigned nrDDD = 0;
03663 unsigned nrDifferentialAdrDD = 0;
03664 bool isDifferential = false;
03665 unsigned u = 0;
03666 bool setToUseOnlyDifferential = true;
03667
03668 double lat = 0;
03669 double lon = 0;
03670 double hgt = 0;
03671 double clk = 0;
03672 double vn = 0;
03673 double ve = 0;
03674 double vup = 0;
03675 double clkdrift = 0;
03676 double M = 0;
03677 double N = 0;
03678
03679 Matrix H_p;
03680 Matrix H_v;
03681 Matrix H;
03682 Matrix r;
03683 Matrix R_p;
03684 Matrix R_v;
03685 Matrix w_p;
03686 Matrix w_v;
03687 Matrix w_adr;
03688 Matrix w;
03689 Matrix K;
03690 Matrix tmpMat;
03691 Matrix tmpMatP;
03692 Matrix dx(8);
03693 Matrix I;
03694
03695 dx.Zero();
03696
03697
03698 lat = rxData->m_pvt.latitude;
03699 lon = rxData->m_pvt.longitude;
03700 hgt = rxData->m_pvt.height;
03701 clk = rxData->m_pvt.clockOffset;
03702 vn = rxData->m_pvt.vn;
03703 ve = rxData->m_pvt.ve;
03704 vup = rxData->m_pvt.vup;
03705 clkdrift = rxData->m_pvt.clockDrift;
03706
03707 if( rxBaseData != NULL )
03708 isDifferential = true;
03709
03710 #ifdef CONSTRAINPOS
03711 rxData->m_pvt.isPositionConstrained = 1;
03712 #else
03713 rxData->m_pvt.isPositionConstrained = 0;
03714 #endif
03715
03716
03717
03718
03719
03720
03721 result = UpdateTime( *rxData );
03722 if( !result )
03723 return false;
03724
03725 if( isDifferential )
03726 {
03727 result = UpdateTime( *rxBaseData );
03728 if( !result )
03729 {
03730 return false;
03731 }
03732 }
03733
03734 result = DetermineSatellitePVT_GPSL1( rxData, rxBaseData, nrValidEph );
03735 if( !result )
03736 {
03737 return false;
03738 }
03739
03740
03741 result = DetermineAtmosphericCorrections_GPSL1( *rxData );
03742 if( !result )
03743 {
03744 return false;
03745 }
03746 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxData, nrP );
03747 if( !result )
03748 {
03749 return false;
03750 }
03751 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxData, nrD );
03752 if( !result )
03753 {
03754 return false;
03755 }
03756 result = DetermineUsableAdrMeasurements_GPSL1( *rxData, nrUsableAdr );
03757 if( !result )
03758 {
03759 return false;
03760 }
03761
03762 if( isDifferential )
03763 {
03764 result = DetermineAtmosphericCorrections_GPSL1( *rxBaseData );
03765 if( !result )
03766 return false;
03767 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxBaseData, nrP_base );
03768 if( !result )
03769 return false;
03770 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxBaseData, nrD_base );
03771 if( !result )
03772 return false;
03773 result = DetermineUsableAdrMeasurements_GPSL1( *rxBaseData, nrUsableAdr_base );
03774 if( !result )
03775 {
03776 return false;
03777 }
03778
03779
03780 result = DetermineBetweenReceiverDifferentialIndex(
03781 rxData,
03782 rxBaseData,
03783 true
03784 );
03785 if( !result )
03786 return false;
03787
03788 nrDifferentialPsr = 0;
03789 for( i = 0; i < rxData->m_nrValidObs; i++ )
03790 {
03791 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
03792 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
03793 rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
03794 {
03795 nrDifferentialPsr++;
03796 }
03797 }
03798
03799 #ifdef CONSTRAINPOS
03800 nrP = nrDifferentialPsr+3;
03801 #else
03802 nrP = nrDifferentialPsr;
03803 #endif
03804
03805 nrDifferentialDoppler = 0;
03806 for( i = 0; i < rxData->m_nrValidObs; i++ )
03807 {
03808 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
03809 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
03810 rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
03811 {
03812 nrDifferentialDoppler++;
03813 }
03814 }
03815
03816 #ifdef CONSTRAINPOS
03817 nrD = nrDifferentialDoppler+3;
03818 #else
03819 nrD = nrDifferentialDoppler;
03820 #endif
03821
03822 nrDifferentialAdr = 0;
03823 for( i = 0; i < rxData->m_nrValidObs; i++ )
03824 {
03825 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
03826 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
03827 rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
03828 {
03829 nrDifferentialAdr++;
03830 }
03831 }
03832
03833 }
03834 else
03835 {
03836 return false;
03837 }
03838
03839 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
03840 *rxData,
03841 nrP,
03842 H_p );
03843 if( !result )
03844 {
03845 return false;
03846 }
03847
03848 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
03849 *rxData,
03850 nrD,
03851 H_v );
03852 if( !result )
03853 {
03854 return false;
03855 }
03856
03857 result = DeterminePseudorangeMisclosures_GPSL1(
03858 rxData,
03859 rxBaseData,
03860 nrP,
03861 w_p );
03862 if( !result )
03863 {
03864 return false;
03865 }
03866
03867 result = DetermineDopplerMisclosures_GPSL1(
03868 rxData,
03869 rxBaseData,
03870 nrD,
03871 w_v );
03872 if( !result )
03873 {
03874 return false;
03875 }
03876
03877 bool hasAmbiguityChangeOccurred = false;
03878 result = DetermineAmbiguitiesChanges(
03879 rxData,
03880 rxBaseData,
03881 P,
03882 hasAmbiguityChangeOccurred );
03883 if( !result )
03884 return false;
03885
03886 if( hasAmbiguityChangeOccurred )
03887 int gagagagag=101;
03888
03889
03890
03891
03892 result = DetermineSingleDifferenceADR_Misclosures_GPSL1(
03893 rxData,
03894 rxBaseData,
03895 nrDifferentialAdr,
03896 w_adr );
03897 if( !result )
03898 {
03899 return false;
03900 }
03901
03902
03903
03904 n = nrP + nrD + nrDifferentialAdr;
03905
03906 if( hasAmbiguityChangeOccurred )
03907 int gg=99;
03908
03909 result = H.Resize( n, 8 + nrDifferentialAdr );
03910 if( !result )
03911 {
03912 return false;
03913 }
03914
03915 result = r.Resize( n );
03916 if( !result )
03917 {
03918 return false;
03919 }
03920
03921 unsigned int iP = 0;
03922 unsigned int iD = 0;
03923 unsigned int iA = 0;
03924 double stdev;
03925 for( k = 0; k < rxData->m_nrValidObs; k++ )
03926 {
03927 if( rxData->m_ObsArray[k].flags.isActive )
03928 {
03929 if( rxData->m_ObsArray[k].flags.isPsrUsedInSolution )
03930 {
03931 H[iP][0] = rxData->m_ObsArray[k].H_p[0];
03932 H[iP][1] = rxData->m_ObsArray[k].H_p[1];
03933 H[iP][2] = rxData->m_ObsArray[k].H_p[2];
03934 H[iP][6] = 1.0;
03935
03936 stdev = rxData->m_ObsArray[k].stdev_psr;
03937 r[iP] = stdev*stdev;
03938 iP++;
03939 }
03940 if( rxData->m_ObsArray[k].flags.isDopplerUsedInSolution )
03941 {
03942 H[iD+nrP][3] = rxData->m_ObsArray[k].H_v[0];
03943 H[iD+nrP][4] = rxData->m_ObsArray[k].H_v[1];
03944 H[iD+nrP][5] = rxData->m_ObsArray[k].H_v[2];
03945 H[iD+nrP][7] = 1.0;
03946 stdev = rxData->m_ObsArray[k].stdev_doppler * GPS_WAVELENGTHL1;
03947 r[iD+nrP] = stdev*stdev;
03948 iD++;
03949 }
03950 if( rxData->m_ObsArray[k].flags.isAdrUsedInSolution )
03951 {
03952 H[iA+nrP+nrD][0] = rxData->m_ObsArray[k].H_p[0];
03953 H[iA+nrP+nrD][1] = rxData->m_ObsArray[k].H_p[1];
03954 H[iA+nrP+nrD][2] = rxData->m_ObsArray[k].H_p[2];
03955 H[iA+nrP+nrD][6] = 1.0;
03956
03957
03958
03959
03960 stdev = rxData->m_ObsArray[k].stdev_adr * GPS_WAVELENGTHL1;
03961 r[iA+nrP+nrD] = stdev*stdev;
03962 iA++;
03963 }
03964 }
03965 }
03966
03967 Matrix timeMat(1);
03968 timeMat[0] = rxData->m_pvt.time.gps_tow;
03969 PrintMatToDebug( "gpstime", timeMat );
03970 PrintMatToDebug( "H", H );
03971
03972
03973
03974
03975
03976
03977 result = w.Resize( n, 1 );
03978 if( !result )
03979 {
03980 return false;
03981 }
03982 for( i = 0; i < n; i++ )
03983 {
03984 if( i < nrP )
03985 {
03986 w[i] = w_p[i];
03987 }
03988 else if ( i < nrP+nrD )
03989 {
03990 w[i] = w_v[i-nrP];
03991 }
03992 else
03993 {
03994 w[i] = w_adr[i-nrP-nrD];
03995 }
03996 }
03997
03998 PrintMatToDebug( "w", w );
03999
04000
04001
04002
04003 if(nrP == 0)
04004 nrPDD = 0;
04005 else
04006 nrPDD = nrP - 1;
04007 if(nrD == 0)
04008 nrDDD = 0;
04009 else
04010 nrDDD = nrD - 1;
04011 if(nrDifferentialAdr == 0)
04012 nrDifferentialAdrDD = 0;
04013 else
04014 nrDifferentialAdrDD = nrDifferentialAdr - 1;
04015
04016 nDD = nrPDD + nrDDD + nrDifferentialAdrDD;
04017
04018
04019
04020
04021
04022
04023 w = m_RTKDD.B*w;
04024
04025
04026 H = m_RTKDD.B*H;
04027
04028
04029
04030 Matrix R(r.nrows(),r.nrows());
04031 for (i = 0; i < r.nrows(); i++)
04032 R[i][i] = r[i];
04033 R = m_RTKDD.B * R * m_RTKDD.B.Transpose();
04034
04035
04036
04037
04038
04039
04040
04041 H.RemoveColumn(6);
04042 H.RemoveColumn(6);
04043 if( nrDifferentialAdrDD > 0 )
04044 {
04045 H.RemoveColumn(6);
04046 for (i = 0; i < nrDifferentialAdrDD; i++)
04047 H[i + nrPDD + nrDDD][6 + i] = 1.0;
04048 }
04049
04050
04051
04052
04053
04054 tmpMat = H*m_RTKDD.P*H.Transpose() + R;
04055 result = tmpMat.Inplace_Invert();
04056 if( !result )
04057 return false;
04058 K = m_RTKDD.P*H.Transpose()*tmpMat;
04059
04060
04061
04062 dx = K*w;
04063
04064
04065
04066
04067 result = I.Resize( K.nrows(), K.nrows() );
04068 if( !result )
04069 return false;
04070 result = I.Identity();
04071 if( !result )
04072 return false;
04073
04074 m_RTKDD.P = (I - K * H)*m_RTKDD.P;
04075
04076 PrintMatToDebug( "dx", dx );
04077 PrintMatToDebug( "P", m_RTKDD.P );
04078 PrintMatToDebug( "K", K );
04079
04080
04081
04082
04083 hgt += dx[2];
04084
04085
04086
04087 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
04088 GEODESY_REFERENCE_ELLIPSE_WGS84,
04089 lat,
04090 &N );
04091 GEODESY_ComputeMeridianRadiusOfCurvature(
04092 GEODESY_REFERENCE_ELLIPSE_WGS84,
04093 lat,
04094 &M );
04095
04096 lat += dx[0] / ( M + hgt );
04097 lon += dx[1] / (( N + hgt )*cos(lat));
04098
04099 result = rxData->UpdatePositionAndRxClock(
04100 lat,
04101 lon,
04102 hgt,
04103 0.0,
04104 sqrt(m_RTKDD.P[0][0]),
04105 sqrt(m_RTKDD.P[1][1]),
04106 sqrt(m_RTKDD.P[2][2]),
04107 0.0
04108 );
04109 if( !result )
04110 return false;
04111
04112
04113
04114 vn += dx[3];
04115 ve += dx[4];
04116 vup += dx[5];
04117
04118
04119 result = rxData->UpdateVelocityAndClockDrift(
04120 vn,
04121 ve,
04122 vup,
04123 0.0,
04124 sqrt(m_RTKDD.P[3][3]),
04125 sqrt(m_RTKDD.P[4][4]),
04126 sqrt(m_RTKDD.P[5][5]),
04127 0.0 );
04128 if( !result )
04129 return false;
04130
04131
04132
04133
04134
04135 Matrix amb;
04136 if( nrDifferentialAdrDD > 0 )
04137 amb.Resize(nrDifferentialAdrDD);
04138
04139 j = 0;
04140 for( i = 0; i < rxData->m_nrValidObs; i++ )
04141 {
04142 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution && rxData->m_ObsArray[i].index_between_satellite_differential != -1 )
04143 {
04144 rxData->m_ObsArray[i].ambiguity_dd += dx[rxData->m_ObsArray[i].index_ambiguity_state_dd];
04145 amb[j] = rxData->m_ObsArray[i].ambiguity_dd;
04146 j++;
04147 }
04148 }
04149
04150 PrintMatToDebug( "amb", amb );
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163 #ifdef DEBUG_THE_ESTIMATOR
04164 char supermsg[8192];
04165 unsigned nrBytesInBuffer = 0;
04166 rxData->Debug_WriteSuperMsg80CharsWide(
04167 supermsg,
04168 8192,
04169 51.0916666667*DEG2RAD,
04170 -114.0000000000*DEG2RAD,
04171 1000.000,
04172 nrBytesInBuffer );
04173 printf( supermsg );
04174 #endif
04175
04176 return true;
04177 }
04178
04179 bool GNSS_Estimator::FixAmbiguities()
04180 {
04181 return true;
04182 }
04183
04184
04185
04186 bool GNSS_Estimator::Kalman_Update_8StatePVGM_SequentialMode(
04187 GNSS_RxData *rxData,
04188 GNSS_RxData *rxBaseData,
04189 Matrix &P
04190 )
04191 {
04192 bool result = false;
04193 unsigned index = 0;
04194 unsigned i = 0;
04195 unsigned j = 0;
04196 unsigned n = 0;
04197 unsigned nrP = 0;
04198 unsigned nrP_base = 0;
04199 unsigned nrD = 0;
04200 unsigned nrD_base = 0;
04201 unsigned nrValidEph = 0;
04202 unsigned nrDifferentialPsr = 0;
04203 unsigned nrDifferentialDoppler = 0;
04204 bool isDifferential = false;
04205 unsigned u = 0;
04206
04207 double lat = 0;
04208 double lon = 0;
04209 double hgt = 0;
04210 double clk = 0;
04211 double vn = 0;
04212 double ve = 0;
04213 double vup = 0;
04214 double clkdrift = 0;
04215 double M = 0;
04216 double N = 0;
04217
04218 Matrix H_p;
04219 Matrix H_v;
04220 Matrix H;
04221 Matrix R_p;
04222 Matrix R_v;
04223 Matrix R;
04224 Matrix w_p;
04225 Matrix w_v;
04226 Matrix w;
04227 Matrix K;
04228 Matrix tmpMat;
04229 Matrix tmpMatP;
04230 Matrix dx(8);
04231 Matrix I;
04232
04233 dx.Zero();
04234
04235
04236 rxData->m_prev_pvt = rxData->m_pvt;
04237
04238 lat = rxData->m_pvt.latitude;
04239 lon = rxData->m_pvt.longitude;
04240 hgt = rxData->m_pvt.height;
04241 clk = rxData->m_pvt.clockOffset;
04242 vn = rxData->m_pvt.vn;
04243 ve = rxData->m_pvt.ve;
04244 vup = rxData->m_pvt.vup;
04245 clkdrift = rxData->m_pvt.clockDrift;
04246
04247 if( rxBaseData != NULL )
04248 isDifferential = true;
04249
04250 #ifdef CONSTRAINPOS
04251 rxData->m_pvt.isPositionConstrained = 1;
04252 #else
04253 rxData->m_pvt.isPositionConstrained = 0;
04254 #endif
04255
04256
04257
04258
04259
04260
04261 result = UpdateTime( *rxData );
04262 if( !result )
04263 return false;
04264
04265 if( isDifferential )
04266 {
04267 result = UpdateTime( *rxBaseData );
04268 if( !result )
04269 {
04270 return false;
04271 }
04272 }
04273
04274 result = DetermineSatellitePVT_GPSL1( rxData, rxBaseData, nrValidEph );
04275 if( !result )
04276 {
04277 return false;
04278 }
04279
04280
04281 result = DetermineAtmosphericCorrections_GPSL1( *rxData );
04282 if( !result )
04283 {
04284 return false;
04285 }
04286 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxData, nrP );
04287 if( !result )
04288 {
04289 return false;
04290 }
04291 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxData, nrD );
04292 if( !result )
04293 {
04294 return false;
04295 }
04296
04297 if( isDifferential )
04298 {
04299 result = DetermineAtmosphericCorrections_GPSL1( *rxBaseData );
04300 if( !result )
04301 return false;
04302 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxBaseData, nrP_base );
04303 if( !result )
04304 return false;
04305 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxBaseData, nrD_base );
04306 if( !result )
04307 return false;
04308
04309
04310
04311 result = DetermineBetweenReceiverDifferentialIndex(
04312 rxData,
04313 rxBaseData,
04314 true
04315 );
04316 if( !result )
04317 return false;
04318
04319 nrDifferentialPsr = 0;
04320 for( i = 0; i < rxData->m_nrValidObs; i++ )
04321 {
04322 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
04323 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
04324 rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
04325 {
04326 nrDifferentialPsr++;
04327 }
04328 }
04329
04330
04331 #ifdef CONSTRAINPOS
04332 nrP = nrDifferentialPsr+3;
04333 #else
04334 nrP = nrDifferentialPsr;
04335 #endif
04336
04337 nrDifferentialDoppler = 0;
04338 for( i = 0; i < rxData->m_nrValidObs; i++ )
04339 {
04340 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
04341 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
04342 rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
04343 {
04344 nrDifferentialDoppler++;
04345 }
04346 }
04347
04348 #ifdef CONSTRAINPOS
04349 nrD = nrDifferentialDoppler+3;
04350 #else
04351 nrD = nrDifferentialDoppler;
04352 #endif
04353 }
04354
04355 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
04356 *rxData,
04357 nrP,
04358 H_p );
04359 if( !result )
04360 {
04361 return false;
04362 }
04363
04364 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
04365 *rxData,
04366 nrD,
04367 H_v );
04368 if( !result )
04369 {
04370 return false;
04371 }
04372
04373
04374 result = DetermineMeasurementVarianceCovarianceMatrixForThePositionSolution_GPSL1(
04375 *rxData,
04376 nrP,
04377 R_p );
04378 if( !result )
04379 {
04380 return false;
04381 }
04382
04383
04384 result = DetermineMeasurementVarianceCovarianceMatrixForTheVelocitySolution_GPSL1(
04385 *rxData,
04386 nrD,
04387 R_v );
04388 if( !result )
04389 {
04390 return false;
04391 }
04392
04393
04394 result = DeterminePseudorangeMisclosures_GPSL1(
04395 rxData,
04396 rxBaseData,
04397 nrP,
04398 w_p );
04399 if( !result )
04400 {
04401 return false;
04402 }
04403
04404 result = DetermineDopplerMisclosures_GPSL1(
04405 rxData,
04406 rxBaseData,
04407 nrD,
04408 w_v );
04409 if( !result )
04410 {
04411 return false;
04412 }
04413
04414
04415 n = H_p.GetNrRows() + H_v.GetNrRows();
04416
04417 result = H.Resize( n, 8 );
04418 if( !result )
04419 {
04420 return false;
04421 }
04422
04423 for( i = 0; i < n; i++ )
04424 {
04425 if( i < nrP )
04426 {
04427 for( j = 0; j < 3; j++ )
04428 {
04429 H[i][j] = H_p[i][j];
04430 }
04431 #ifdef CONSTRAINPOS
04432 if( i < nrP-3 )
04433 {
04434 H[i][6] = 1.0;
04435 }
04436 #else
04437 H[i][6] = 1.0;
04438 #endif
04439 }
04440 else
04441 {
04442 for( j = 0; j < 3; j++ )
04443 {
04444 H[i][j+3] = H_v[i-nrP][j];
04445 }
04446 #ifdef CONSTRAINPOS
04447 if( i < n-3 )
04448 {
04449 H[i][7] = 1.0;
04450 }
04451 #else
04452 H[i][7] = 1.0;
04453 #endif
04454 }
04455 }
04456
04457
04458 result = R.Resize( n, n );
04459 if( !result )
04460 {
04461 return false;
04462 }
04463
04464
04465 for( i = 0; i < n; i++ )
04466 {
04467 if( i < nrP )
04468 {
04469 for( j = 0; j < nrP; j++ )
04470 {
04471 R[i][j] = R_p[i][j];
04472 }
04473 }
04474 else
04475 {
04476 for( j = 0; j < nrD; j++ )
04477 {
04478 R[i][j+nrD] = R_v[i-nrP][j];
04479 }
04480 }
04481 }
04482
04483
04484
04485 result = w.Resize( n, 1 );
04486 if( !result )
04487 {
04488 return false;
04489 }
04490 for( i = 0; i < n; i++ )
04491 {
04492 if( i < nrP )
04493 {
04494 w[i] = w_p[i];
04495 }
04496 else
04497 {
04498 w[i] = w_v[i-nrP];
04499 }
04500 }
04501
04502
04503 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
04504 GEODESY_REFERENCE_ELLIPSE_WGS84,
04505 lat,
04506 &N );
04507 GEODESY_ComputeMeridianRadiusOfCurvature(
04508 GEODESY_REFERENCE_ELLIPSE_WGS84,
04509 lat,
04510 &M );
04511 double dlat = M + hgt;
04512 double dlon = (N + hgt) * cos(lat);
04513
04514 u = 8;
04515
04516
04517 for( index = 0; index < n; index++ )
04518 {
04519 Matrix h(1,u);
04520 Matrix ht(u,1);
04521 Matrix pht;
04522 Matrix C;
04523 Matrix k_i;
04524 Matrix D;
04525
04526
04527 for( j = 0; j < u; j++ )
04528 {
04529 h[0][j] = H[index][j];
04530 ht[j][0] = H[index][j];
04531 }
04532
04533
04534
04535 pht = P;
04536 if( !pht.Inplace_PostMultiply( ht ) )
04537 return false;
04538
04539
04540 C = h * pht;
04541 C[0] += R[index][index];
04542
04543
04544 k_i = pht / C[0];
04545
04546
04547
04548
04549 D = k_i;
04550 if( !D.Inplace_PostMultiply( h ) )
04551 return false;
04552 if( !D.Inplace_PostMultiply( P ) )
04553 return false;
04554 P -= D;
04555
04556
04557 double innovation = w[index];
04558 k_i.Inplace_MultiplyScalar( innovation );
04559 dx = k_i;
04560
04561
04562
04563
04564 hgt += dx[2];
04565 clk += dx[6];
04566
04567
04568 lat += dx[0] / dlat;
04569 lon += dx[1] / dlon;
04570
04571 result = rxData->UpdatePositionAndRxClock(
04572 lat,
04573 lon,
04574 hgt,
04575 clk,
04576 sqrt(P[0][0]),
04577 sqrt(P[1][1]),
04578 sqrt(P[2][2]),
04579 sqrt(P[6][6])
04580 );
04581 if( !result )
04582 {
04583 return false;
04584 }
04585
04586
04587 vn += dx[3];
04588 ve += dx[4];
04589 vup += dx[5];
04590 clkdrift += dx[7];
04591
04592 result = rxData->UpdateVelocityAndClockDrift(
04593 vn,
04594 ve,
04595 vup,
04596 clkdrift,
04597 sqrt(P[3][3]),
04598 sqrt(P[4][4]),
04599 sqrt(P[5][5]),
04600 sqrt(P[7][7]) );
04601 if( !result )
04602 {
04603 return false;
04604 }
04605
04606 result = DeterminePseudorangeMisclosures_GPSL1(
04607 rxData,
04608 rxBaseData,
04609 nrP,
04610 w_p );
04611 if( !result )
04612 {
04613 return false;
04614 }
04615
04616 result = DetermineDopplerMisclosures_GPSL1(
04617 rxData,
04618 rxBaseData,
04619 nrD,
04620 w_v );
04621 if( !result )
04622 {
04623 return false;
04624 }
04625
04626 for( i = 0; i < n; i++ )
04627 {
04628 if( i < nrP )
04629 {
04630 w[i] = w_p[i];
04631 }
04632 else
04633 {
04634 w[i] = w_v[i-nrP];
04635 }
04636 }
04637 }
04638 return true;
04639 }
04640
04641
04642
04643 bool GNSS_Estimator::Kalman_Update_8StatePVGM_SequentialMode_FloatSolution(
04644 GNSS_RxData *rxData,
04645 GNSS_RxData *rxBaseData,
04646 Matrix &P
04647 )
04648 {
04649 bool result = false;
04650 unsigned index = 0;
04651 unsigned i = 0;
04652 unsigned j = 0;
04653 unsigned k = 0;
04654 unsigned m = 0;
04655 unsigned n = 0;
04656 unsigned nrP = 0;
04657 unsigned nrP_base = 0;
04658 unsigned nrD = 0;
04659 unsigned nrD_base = 0;
04660 unsigned nrValidEph = 0;
04661 unsigned nrUsableAdr = 0;
04662 unsigned nrUsableAdr_base = 0;
04663 unsigned nrDifferentialPsr = 0;
04664 unsigned nrDifferentialDoppler = 0;
04665 unsigned nrDifferentialAdr = 0;
04666 bool isDifferential = false;
04667 unsigned u = 0;
04668 bool setToUseOnlyDifferential = true;
04669
04670 double lat = 0;
04671 double lon = 0;
04672 double hgt = 0;
04673 double clk = 0;
04674 double vn = 0;
04675 double ve = 0;
04676 double vup = 0;
04677 double clkdrift = 0;
04678 double M = 0;
04679 double N = 0;
04680
04681 Matrix H_p;
04682 Matrix H_v;
04683 Matrix H;
04684 Matrix r;
04685 Matrix R_p;
04686 Matrix R_v;
04687 Matrix w_p;
04688 Matrix w_v;
04689 Matrix w_adr;
04690 Matrix w;
04691 Matrix K;
04692 Matrix tmpMat;
04693 Matrix tmpMatP;
04694 Matrix dx(8);
04695 Matrix I;
04696
04697 dx.Zero();
04698
04699
04700 lat = rxData->m_pvt.latitude;
04701 lon = rxData->m_pvt.longitude;
04702 hgt = rxData->m_pvt.height;
04703 clk = rxData->m_pvt.clockOffset;
04704 vn = rxData->m_pvt.vn;
04705 ve = rxData->m_pvt.ve;
04706 vup = rxData->m_pvt.vup;
04707 clkdrift = rxData->m_pvt.clockDrift;
04708
04709 if( rxBaseData != NULL )
04710 isDifferential = true;
04711
04712 #ifdef CONSTRAINPOS
04713 rxData->m_pvt.isPositionConstrained = 1;
04714 #else
04715 rxData->m_pvt.isPositionConstrained = 0;
04716 #endif
04717
04718
04719
04720
04721
04722
04723 result = UpdateTime( *rxData );
04724 if( !result )
04725 return false;
04726
04727 if( isDifferential )
04728 {
04729 result = UpdateTime( *rxBaseData );
04730 if( !result )
04731 {
04732 return false;
04733 }
04734 }
04735
04736 result = DetermineSatellitePVT_GPSL1( rxData, rxBaseData, nrValidEph );
04737 if( !result )
04738 {
04739 return false;
04740 }
04741
04742
04743 result = DetermineAtmosphericCorrections_GPSL1( *rxData );
04744 if( !result )
04745 {
04746 return false;
04747 }
04748 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxData, nrP );
04749 if( !result )
04750 {
04751 return false;
04752 }
04753 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxData, nrD );
04754 if( !result )
04755 {
04756 return false;
04757 }
04758 result = DetermineUsableAdrMeasurements_GPSL1( *rxData, nrUsableAdr );
04759 if( !result )
04760 {
04761 return false;
04762 }
04763
04764 if( isDifferential )
04765 {
04766 result = DetermineAtmosphericCorrections_GPSL1( *rxBaseData );
04767 if( !result )
04768 return false;
04769 result = DetermineUsablePseudorangeMeasurementsForThePositionSolution_GPSL1( *rxBaseData, nrP_base );
04770 if( !result )
04771 return false;
04772 result = DetermineUsableDopplerMeasurementsForTheVelocitySolution_GPSL1( *rxBaseData, nrD_base );
04773 if( !result )
04774 return false;
04775 result = DetermineUsableAdrMeasurements_GPSL1( *rxBaseData, nrUsableAdr_base );
04776 if( !result )
04777 {
04778 return false;
04779 }
04780
04781
04782 result = DetermineBetweenReceiverDifferentialIndex(
04783 rxData,
04784 rxBaseData,
04785 true
04786 );
04787 if( !result )
04788 return false;
04789
04790 nrDifferentialPsr = 0;
04791 for( i = 0; i < rxData->m_nrValidObs; i++ )
04792 {
04793 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
04794 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
04795 rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
04796 {
04797 nrDifferentialPsr++;
04798 }
04799 }
04800
04801 #ifdef CONSTRAINPOS
04802 nrP = nrDifferentialPsr+3;
04803 #else
04804 nrP = nrDifferentialPsr;
04805 #endif
04806
04807 nrDifferentialDoppler = 0;
04808 for( i = 0; i < rxData->m_nrValidObs; i++ )
04809 {
04810 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
04811 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
04812 rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
04813 {
04814 nrDifferentialDoppler++;
04815 }
04816 }
04817
04818 #ifdef CONSTRAINPOS
04819 nrD = nrDifferentialDoppler+3;
04820 #else
04821 nrD = nrDifferentialDoppler;
04822 #endif
04823
04824 nrDifferentialAdr = 0;
04825 for( i = 0; i < rxData->m_nrValidObs; i++ )
04826 {
04827 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
04828 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
04829 rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
04830 {
04831 nrDifferentialAdr++;
04832 }
04833 }
04834
04835 }
04836 else
04837 {
04838 return false;
04839 }
04840
04841 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
04842 *rxData,
04843 nrP,
04844 H_p );
04845 if( !result )
04846 {
04847 return false;
04848 }
04849
04850 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
04851 *rxData,
04852 nrD,
04853 H_v );
04854 if( !result )
04855 {
04856 return false;
04857 }
04858
04859 result = DeterminePseudorangeMisclosures_GPSL1(
04860 rxData,
04861 rxBaseData,
04862 nrP,
04863 w_p );
04864 if( !result )
04865 {
04866 return false;
04867 }
04868
04869 result = DetermineDopplerMisclosures_GPSL1(
04870 rxData,
04871 rxBaseData,
04872 nrD,
04873 w_v );
04874 if( !result )
04875 {
04876 return false;
04877 }
04878
04879 bool hasAmbiguityChangeOccurred = false;
04880 result = DetermineAmbiguitiesChanges(
04881 rxData,
04882 rxBaseData,
04883 P,
04884 hasAmbiguityChangeOccurred );
04885 if( !result )
04886 return false;
04887
04888 result = DetermineSingleDifferenceADR_Misclosures_GPSL1(
04889 rxData,
04890 rxBaseData,
04891 nrDifferentialAdr,
04892 w_adr );
04893 if( !result )
04894 {
04895 return false;
04896 }
04897
04898
04899
04900 n = nrP + nrD + nrDifferentialAdr;
04901
04902 if( hasAmbiguityChangeOccurred )
04903 int gg=99;
04904
04905 result = H.Resize( n, 8 + nrDifferentialAdr );
04906 if( !result )
04907 {
04908 return false;
04909 }
04910
04911 result = r.Resize( n );
04912 if( !result )
04913 {
04914 return false;
04915 }
04916
04917 unsigned int iP = 0;
04918 unsigned int iD = 0;
04919 unsigned int iA = 0;
04920 double stdev;
04921 for( k = 0; k < rxData->m_nrValidObs; k++ )
04922 {
04923 if( rxData->m_ObsArray[k].flags.isActive )
04924 {
04925 if( rxData->m_ObsArray[k].flags.isPsrUsedInSolution )
04926 {
04927 H[iP][0] = rxData->m_ObsArray[k].H_p[0];
04928 H[iP][1] = rxData->m_ObsArray[k].H_p[1];
04929 H[iP][2] = rxData->m_ObsArray[k].H_p[2];
04930 H[iP][6] = 1.0;
04931
04932 stdev = rxData->m_ObsArray[k].stdev_psr;
04933 r[iP] = stdev*stdev;
04934 iP++;
04935 }
04936 if( rxData->m_ObsArray[k].flags.isDopplerUsedInSolution )
04937 {
04938 H[iD+nrP][3] = rxData->m_ObsArray[k].H_v[0];
04939 H[iD+nrP][4] = rxData->m_ObsArray[k].H_v[1];
04940 H[iD+nrP][5] = rxData->m_ObsArray[k].H_v[2];
04941 H[iD+nrP][7] = 1.0;
04942 stdev = rxData->m_ObsArray[k].stdev_doppler * GPS_WAVELENGTHL1;
04943 r[iD+nrP] = stdev*stdev;
04944 iD++;
04945 }
04946 if( rxData->m_ObsArray[k].flags.isAdrUsedInSolution )
04947 {
04948 H[iA+nrP+nrD][0] = rxData->m_ObsArray[k].H_p[0];
04949 H[iA+nrP+nrD][1] = rxData->m_ObsArray[k].H_p[1];
04950 H[iA+nrP+nrD][2] = rxData->m_ObsArray[k].H_p[2];
04951 H[iA+nrP+nrD][6] = 1.0;
04952
04953 H[iA+nrP+nrD][rxData->m_ObsArray[k].index_ambiguity_state] = 1.0;
04954
04955 stdev = rxData->m_ObsArray[k].stdev_adr * GPS_WAVELENGTHL1;
04956 r[iA+nrP+nrD] = stdev*stdev;
04957 iA++;
04958 }
04959 }
04960 }
04961
04962 Matrix timeMat(1);
04963 timeMat[0] = rxData->m_pvt.time.gps_tow;
04964 PrintMatToDebug( "gpstime", timeMat );
04965 PrintMatToDebug( "H", H );
04966
04967
04968 result = w.Resize( n, 1 );
04969 if( !result )
04970 {
04971 return false;
04972 }
04973 for( i = 0; i < n; i++ )
04974 {
04975 if( i < nrP )
04976 {
04977 w[i] = w_p[i];
04978 }
04979 else if ( i < nrP+nrD )
04980 {
04981 w[i] = w_v[i-nrP];
04982 }
04983 else
04984 {
04985 w[i] = w_adr[i-nrP-nrD];
04986 }
04987 }
04988
04989 PrintMatToDebug( "w", w );
04990
04991
04992 GEODESY_ComputePrimeVerticalRadiusOfCurvature(
04993 GEODESY_REFERENCE_ELLIPSE_WGS84,
04994 lat,
04995 &N );
04996 GEODESY_ComputeMeridianRadiusOfCurvature(
04997 GEODESY_REFERENCE_ELLIPSE_WGS84,
04998 lat,
04999 &M );
05000 double dlat = M + hgt;
05001 double dlon = (N + hgt) * cos(lat);
05002
05003 Matrix amb;
05004 if( nrDifferentialAdr > 0 )
05005 amb.Resize(nrDifferentialAdr);
05006
05007 u = 8 + nrDifferentialAdr;
05008
05009
05010 for( index = 0; index < n; index++ )
05011 {
05012 Matrix h(1,u);
05013 Matrix ht(u,1);
05014 Matrix pht;
05015 Matrix C;
05016 Matrix k_i;
05017 Matrix D;
05018
05019
05020 for( j = 0; j < u; j++ )
05021 {
05022 h[0][j] = H[index][j];
05023 ht[j][0] = H[index][j];
05024 }
05025
05026
05027
05028 pht = P;
05029 if( !pht.Inplace_PostMultiply( ht ) )
05030 return false;
05031
05032
05033 C = h * pht;
05034 C[0] += r[index];
05035
05036
05037 k_i = pht / C[0];
05038
05039
05040
05041
05042 D = k_i;
05043 if( !D.Inplace_PostMultiply( h ) )
05044 return false;
05045 if( !D.Inplace_PostMultiply( P ) )
05046 return false;
05047 P -= D;
05048
05049 double innovation = w[index];
05050 k_i.Inplace_MultiplyScalar( innovation );
05051 dx = k_i;
05052
05053
05054
05055
05056 hgt += dx[2];
05057 clk += dx[6];
05058
05059
05060 lat += dx[0] / dlat;
05061 lon += dx[1] / dlon;
05062
05063 result = rxData->UpdatePositionAndRxClock(
05064 lat,
05065 lon,
05066 hgt,
05067 clk,
05068 sqrt(P[0][0]),
05069 sqrt(P[1][1]),
05070 sqrt(P[2][2]),
05071 sqrt(P[6][6])
05072 );
05073 if( !result )
05074 {
05075 return false;
05076 }
05077
05078
05079 vn += dx[3];
05080 ve += dx[4];
05081 vup += dx[5];
05082 clkdrift += dx[7];
05083
05084 result = rxData->UpdateVelocityAndClockDrift(
05085 vn,
05086 ve,
05087 vup,
05088 clkdrift,
05089 sqrt(P[3][3]),
05090 sqrt(P[4][4]),
05091 sqrt(P[5][5]),
05092 sqrt(P[7][7]) );
05093 if( !result )
05094 {
05095 return false;
05096 }
05097
05098
05099 result = DetermineDesignMatrixForThePositionSolution_GPSL1(
05100 *rxData,
05101 nrP,
05102 H_p );
05103 if( !result )
05104 {
05105 return false;
05106 }
05107
05108 result = DetermineDesignMatrixForTheVelocitySolution_GPSL1(
05109 *rxData,
05110 nrD,
05111 H_v );
05112 if( !result )
05113 {
05114 return false;
05115 }
05116
05117 result = DeterminePseudorangeMisclosures_GPSL1(
05118 rxData,
05119 rxBaseData,
05120 nrP,
05121 w_p );
05122 if( !result )
05123 {
05124 return false;
05125 }
05126
05127 result = DetermineDopplerMisclosures_GPSL1(
05128 rxData,
05129 rxBaseData,
05130 nrD,
05131 w_v );
05132 if( !result )
05133 {
05134 return false;
05135 }
05136
05137 j = 0;
05138 for( i = 0; i < rxData->m_nrValidObs; i++ )
05139 {
05140 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05141 {
05142 rxData->m_ObsArray[i].ambiguity += dx[rxData->m_ObsArray[i].index_ambiguity_state];
05143 amb[j] = rxData->m_ObsArray[i].ambiguity;
05144 j++;
05145 }
05146 }
05147
05148 result = DetermineSingleDifferenceADR_Misclosures_GPSL1(
05149 rxData,
05150 rxBaseData,
05151 nrDifferentialAdr,
05152 w_adr );
05153
05154 for( i = 0; i < n; i++ )
05155 {
05156 if( i < nrP )
05157 {
05158 w[i] = w_p[i];
05159 }
05160 else if( i < nrP+nrD )
05161 {
05162 w[i] = w_v[i-nrP];
05163 }
05164 else
05165 {
05166 w[i] = w_adr[i-nrP-nrD];
05167 }
05168 }
05169 }
05170
05171 for( i = 0; i < rxData->m_nrValidObs; i++ )
05172 {
05173 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
05174 rxData->m_pvt.nrPsrObsUsed++;
05175 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
05176 rxData->m_pvt.nrDopplerObsUsed++;
05177 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05178 rxData->m_pvt.nrAdrObsUsed++;
05179 }
05180
05181
05182 #ifdef DEBUG_THE_ESTIMATOR
05183 char supermsg[8192];
05184 unsigned nrBytesInBuffer = 0;
05185 rxData->Debug_WriteSuperMsg80CharsWide(
05186 supermsg,
05187 8192,
05188 51.0916666667*DEG2RAD,
05189 -114.0000000000*DEG2RAD,
05190 1000.000,
05191 nrBytesInBuffer );
05192 printf( supermsg );
05193 #endif
05194
05195 return true;
05196 }
05197
05198
05199 bool GNSS_Estimator::PrintMatToDebug( const char *name, Matrix& M )
05200 {
05201 #ifdef DEBUG_THE_ESTIMATOR
05202
05203 char buffer[8192];
05204 if( name == NULL )
05205 return false;
05206 if( !M.PrintToBuffer( buffer, 8192, 7 ) )
05207 return 1;
05208 printf( "%s = \n%s\n", name, buffer );
05209
05210 if( m_debug == NULL )
05211 {
05212 m_debug = fopen( "debug.txt", "w" );
05213 if( !m_debug )
05214 {
05215 return false;
05216 }
05217 }
05218 else
05219 {
05220 fprintf( m_debug, "%s = \n%s\n", name, buffer );
05221 fflush( m_debug );
05222 }
05223 #endif
05224 return true;
05225 }
05226
05227
05228
05229 bool GNSS_Estimator::DetermineAmbiguitiesChanges(
05230 GNSS_RxData *rxData,
05231 GNSS_RxData *rxBaseData,
05232 Matrix &P,
05233 bool& changeOccured
05234 )
05235 {
05236 unsigned i = 0;
05237 unsigned j = 0;
05238 unsigned k = 0;
05239 unsigned m = 0;
05240 unsigned iP = 0;
05241 unsigned iD = 0;
05242 unsigned iA = 0;
05243 unsigned nP = 0;
05244 unsigned nD = 0;
05245 unsigned nA = 0;
05246
05247 bool isAmbiguityActive = false;
05248 std::list<stAmbiguityInfo>::iterator iter;
05249 std::list<stAmbiguityInfo>::iterator check_iter;
05250 std::list<stAmbiguityInfo>::iterator remove_iter;
05251 std::list<unsigned int> remove_list;
05252 std::list<unsigned int>::const_iterator list_iter;
05253
05254 changeOccured = false;
05255
05256
05257
05258
05259 for( iter = m_ActiveAmbiguitiesList.begin(); iter != m_ActiveAmbiguitiesList.end(); )
05260 {
05261 isAmbiguityActive = false;
05262
05263
05264
05265 for( i = 0; i < rxData->m_nrValidObs; i++ )
05266 {
05267 if(
05268 iter->id == rxData->m_ObsArray[i].id &&
05269 iter->system == rxData->m_ObsArray[i].system &&
05270 iter->freqType == rxData->m_ObsArray[i].freqType &&
05271 rxData->m_ObsArray[i].flags.isAdrUsedInSolution &&
05272 rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
05273 {
05274
05275 isAmbiguityActive = true;
05276 break;
05277 }
05278 }
05279
05280 if( !isAmbiguityActive )
05281 {
05282 changeOccured = true;
05283
05284
05285
05286 remove_list.push_back( iter->state_index );
05287
05288 remove_iter = iter;
05289 ++iter;
05290 m_ActiveAmbiguitiesList.erase( remove_iter );
05291 }
05292 else
05293 {
05294 ++iter;
05295 }
05296 }
05297
05298
05299 if( remove_list.size() > 0 )
05300 {
05301 unsigned int *rows = NULL;
05302 unsigned int nrows = static_cast<unsigned int>(remove_list.size());
05303 rows = new unsigned int[nrows];
05304 if( rows == NULL )
05305 {
05306 return false;
05307 }
05308
05309 i = 0;
05310 for( list_iter = remove_list.begin(); list_iter != remove_list.end(); ++list_iter )
05311 {
05312 rows[i] = *list_iter;
05313 i++;
05314 }
05315
05316
05317 if( !P.RemoveRowsAndColumns( nrows, rows, nrows, rows ) )
05318 {
05319 return false;
05320 }
05321
05322
05323 delete [] rows;
05324 }
05325
05326
05327
05328 for( iter = m_ActiveAmbiguitiesList.begin(); iter != m_ActiveAmbiguitiesList.end(); ++iter )
05329 {
05330 for( list_iter = remove_list.begin(); list_iter != remove_list.end(); ++list_iter )
05331 {
05332 if( iter->state_index > (int)(*list_iter) )
05333 {
05334 iter->state_index -= 1;
05335 }
05336 }
05337
05338 for( i = 0; i < rxData->m_nrValidObs; i++ )
05339 {
05340 if(
05341 iter->id == rxData->m_ObsArray[i].id &&
05342 iter->system == rxData->m_ObsArray[i].system &&
05343 iter->freqType == rxData->m_ObsArray[i].freqType &&
05344 rxData->m_ObsArray[i].flags.isAdrUsedInSolution &&
05345 rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
05346 {
05347 rxData->m_ObsArray[i].index_ambiguity_state = iter->state_index;
05348 break;
05349 }
05350 }
05351 }
05352 remove_list.clear();
05353
05354
05355
05356
05357 for( i = 0; i < rxData->m_nrValidObs; i++ )
05358 {
05359 isAmbiguityActive = false;
05360 if( rxData->m_ObsArray[i].system == GNSS_GPS && rxData->m_ObsArray[i].freqType == GNSS_GPSL1 )
05361 {
05362 if( rxData->m_ObsArray[i].flags.isActive )
05363 {
05364 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05365 {
05366
05367 for( iter = m_ActiveAmbiguitiesList.begin(); iter != m_ActiveAmbiguitiesList.end(); ++iter )
05368 {
05369 if(
05370 iter->id == rxData->m_ObsArray[i].id &&
05371 iter->system == rxData->m_ObsArray[i].system &&
05372 iter->freqType == rxData->m_ObsArray[i].freqType &&
05373 rxData->m_ObsArray[i].flags.isDifferentialAdrAvailable )
05374 {
05375
05376 isAmbiguityActive = true;
05377 break;
05378 }
05379 }
05380
05381 if( !isAmbiguityActive )
05382 {
05383 changeOccured = true;
05384
05385
05386 stAmbiguityInfo amb_info;
05387
05388 amb_info.channel = rxData->m_ObsArray[i].channel;
05389 amb_info.id = rxData->m_ObsArray[i].id;
05390 amb_info.system = rxData->m_ObsArray[i].system;
05391 amb_info.freqType = rxData->m_ObsArray[i].freqType;
05392 amb_info.state_index = P.nrows();
05393
05394 rxData->m_ObsArray[i].index_ambiguity_state = amb_info.state_index;
05395
05396 m_ActiveAmbiguitiesList.push_back( amb_info );
05397
05398
05399 if( !P.Redim( P.nrows()+1, P.ncols()+1 ) )
05400 return false;
05401
05402
05403 P[amb_info.state_index][amb_info.state_index] = 125;
05404
05405
05406
05407 double sd_adr_measured = rxData->m_ObsArray[i].adr - rxBaseData->m_ObsArray[rxData->m_ObsArray[i].index_differential].adr;
05408 sd_adr_measured *= GPS_WAVELENGTHL1;
05409
05410
05411 double sd_psr_measured = rxData->m_ObsArray[i].psr - rxBaseData->m_ObsArray[rxData->m_ObsArray[i].index_differential].psr;
05412
05413
05414
05415
05416 rxData->m_ObsArray[i].ambiguity = sd_adr_measured - sd_psr_measured;
05417
05418
05419
05420
05421 }
05422 }
05423 else
05424 {
05425 rxData->m_ObsArray[i].index_ambiguity_state = -1;
05426 rxData->m_ObsArray[i].ambiguity = 0.0;
05427 }
05428 }
05429 }
05430 }
05431
05432
05433 i = 0;
05434 j = 0;
05435 for( iter = m_ActiveAmbiguitiesList.begin(); iter != m_ActiveAmbiguitiesList.end(); ++iter )
05436 {
05437 j=0;
05438 for( check_iter = m_ActiveAmbiguitiesList.begin(); check_iter != m_ActiveAmbiguitiesList.end(); ++check_iter )
05439 {
05440 if( i != j )
05441 {
05442 if( check_iter->state_index == iter->state_index )
05443 return false;
05444 }
05445 j++;
05446 }
05447 i++;
05448 }
05449
05450
05451 if( changeOccured )
05452 {
05453
05454 int ch_index_base = -1;
05455
05456
05457
05458 for( i = 0; i < rxData->m_nrValidObs; i++ )
05459 {
05460 if( rxData->m_ObsArray[i].flags.isActive )
05461 {
05462 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
05463 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
05464 rxData->m_ObsArray[i].flags.isAdrValid &&
05465 rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05466 {
05467 ch_index_base = i;
05468 break;
05469 }
05470 }
05471 }
05472 if( ch_index_base == -1 )
05473 {
05474
05475 return true;
05476 }
05477
05478
05479 for( i = 0; i < rxData->m_nrValidObs; i++ )
05480 {
05481 rxData->m_ObsArray[i].index_between_satellite_differential = -1;
05482 if( rxData->m_ObsArray[i].flags.isActive )
05483 {
05484 if( rxData->m_ObsArray[i].system == GNSS_GPS &&
05485 rxData->m_ObsArray[i].freqType == GNSS_GPSL1 &&
05486 rxData->m_ObsArray[i].flags.isAdrValid &&
05487 rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05488 {
05489 if( i != ch_index_base )
05490 {
05491 rxData->m_ObsArray[i].index_between_satellite_differential = ch_index_base;
05492 }
05493 }
05494 }
05495 }
05496
05497 for( i = 0; i < rxData->m_nrValidObs; i++ )
05498 {
05499 rxData->m_ObsArray[i].index_psr_B = -1;
05500 if( rxData->m_ObsArray[i].flags.isActive )
05501 {
05502 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
05503 {
05504 rxData->m_ObsArray[i].index_psr_B = nP;
05505 nP++;
05506 }
05507 }
05508 }
05509
05510 for( i = 0; i < rxData->m_nrValidObs; i++ )
05511 {
05512 rxData->m_ObsArray[i].index_Doppler_B = -1;
05513 if( rxData->m_ObsArray[i].flags.isActive )
05514 {
05515 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
05516 {
05517 rxData->m_ObsArray[i].index_Doppler_B = nP + nD;
05518 nD++;
05519 }
05520 }
05521 }
05522
05523 for( i = 0; i < rxData->m_nrValidObs; i++ )
05524 {
05525 rxData->m_ObsArray[i].index_adr_B = -1;
05526 if( rxData->m_ObsArray[i].flags.isActive )
05527 {
05528 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05529 {
05530 rxData->m_ObsArray[i].index_adr_B = nP + nD + nA;
05531 nA++;
05532 }
05533 }
05534 }
05535
05536 unsigned n=0;
05537
05538 j = 0;
05539 if( nP > 0 )
05540 {
05541 n += nP - 1;
05542 j++;
05543 }
05544 if( nD > 0 )
05545 {
05546 n += nD - 1;
05547 j++;
05548 }
05549 if( nA > 0 )
05550 {
05551 n += nA - 1;
05552 j++;
05553 }
05554
05555
05556 if( !m_RTKDD.B.Resize( n, n+j ) )
05557 return false;
05558
05559
05560 for( i = 0; i < rxData->m_nrValidObs; i++ )
05561 {
05562 if( rxData->m_ObsArray[i].flags.isActive )
05563 {
05564 if( rxData->m_ObsArray[i].flags.isPsrUsedInSolution )
05565 {
05566 if( rxData->m_ObsArray[i].index_between_satellite_differential != -1 )
05567 {
05568 if( rxData->m_ObsArray[ rxData->m_ObsArray[i].index_between_satellite_differential ].index_psr_B == -1 )
05569 {
05570 return false;
05571 }
05572 m_RTKDD.B[iP][ rxData->m_ObsArray[ rxData->m_ObsArray[i].index_between_satellite_differential ].index_psr_B ] = -1.0;
05573 m_RTKDD.B[iP][ rxData->m_ObsArray[i].index_psr_B ] = 1.0;
05574 iP++;
05575 }
05576 }
05577 }
05578 }
05579
05580
05581 for( i = 0; i < rxData->m_nrValidObs; i++ )
05582 {
05583 if( rxData->m_ObsArray[i].flags.isActive )
05584 {
05585 if( rxData->m_ObsArray[i].flags.isDopplerUsedInSolution )
05586 {
05587 if( rxData->m_ObsArray[i].index_between_satellite_differential != -1 )
05588 {
05589 if( rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_Doppler_B == -1 )
05590 {
05591 return false;
05592 }
05593 m_RTKDD.B[iD+iP][ rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_Doppler_B ] = -1.0;
05594 m_RTKDD.B[iD+iP][ rxData->m_ObsArray[i].index_Doppler_B ] = 1.0;
05595 iD++;
05596 }
05597 }
05598 }
05599 }
05600
05601 if( !m_RTKDD.B.isEmpty() )
05602 m_RTKDD.prevB = m_RTKDD.B;
05603 if( !m_RTKDD.SubB.isEmpty() )
05604 m_RTKDD.prevSubB = m_RTKDD.SubB;
05605
05606 for( i = 0; i < rxData->m_nrValidObs; i++ )
05607 {
05608 if( rxData->m_ObsArray[i].flags.isActive )
05609 {
05610 if( rxData->m_ObsArray[i].flags.isAdrUsedInSolution )
05611 {
05612 if( rxData->m_ObsArray[i].index_between_satellite_differential != -1 )
05613 {
05614 if( rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_adr_B == -1 )
05615 {
05616 return false;
05617 }
05618 m_RTKDD.B[iA+iP+iD][ rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_adr_B ] = -1.0;
05619 m_RTKDD.B[iA+iP+iD][ rxData->m_ObsArray[i].index_adr_B ] = 1.0;
05620
05621
05622
05623
05624
05625 double sd_adr_current = rxData->m_ObsArray[i].adr - rxBaseData->m_ObsArray[rxData->m_ObsArray[i].index_differential].adr;
05626 sd_adr_current *= GPS_WAVELENGTHL1;
05627 double sd_psr_current = rxData->m_ObsArray[i].psr - rxBaseData->m_ObsArray[rxData->m_ObsArray[i].index_differential].psr;
05628
05629 double sd_ambiguity_current = sd_adr_current - sd_psr_current;
05630
05631
05632
05633 double sd_adr_base = rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].adr - rxBaseData->m_ObsArray[rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_differential].adr;
05634 sd_adr_base *= GPS_WAVELENGTHL1;
05635
05636 double sd_psr_base = rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].psr - rxBaseData->m_ObsArray[rxData->m_ObsArray[rxData->m_ObsArray[i].index_between_satellite_differential].index_differential].psr;
05637 double sd_ambiguity_base = sd_adr_base - sd_psr_base;
05638
05639
05640 rxData->m_ObsArray[i].ambiguity_dd = sd_ambiguity_current - sd_ambiguity_base;
05641 iA++;
05642 }
05643 }
05644 }
05645 }
05646 if( iA < 1 )
05647 {
05648
05649 return true;
05650 }
05651
05652 PrintMatToDebug( "B", m_RTKDD.B );
05653
05654 if( !m_RTKDD.SubB.Resize(iA,iA+1) )
05655 return false;
05656
05657 for( i = 0; i < iA; i++ )
05658 {
05659 for( j = 0; j < iA+1; j++ )
05660 {
05661 m_RTKDD.SubB[i][j] = m_RTKDD.B[i+iP+iD][j+nP+nD];
05662 }
05663 }
05664
05665 PrintMatToDebug( "subB", m_RTKDD.SubB );
05666
05667 if( m_RTKDD.prevSubB.isEmpty() )
05668 {
05669
05670 Matrix subP(nA,nA);
05671 for( i = 0; i < nA; i++ )
05672 {
05673 for( j = 0; j < nA; j++ )
05674 {
05675 subP[i][j] = P[i+6][j+6];
05676 }
05677 }
05678
05679 m_RTKDD.P = P;
05680 P.Redim( 6, 6 );
05681 P.Redim( 6+iA, 6+iA );
05682
05683 subP = m_RTKDD.SubB*subP*m_RTKDD.SubB.T();
05684 for( i = 0; i < iA; i++ )
05685 {
05686 for( j = 0; j < iA; j++ )
05687 {
05688 P[i+6][j+6] = subP[i][j];
05689 }
05690 }
05691 PrintMatToDebug( "subP", subP );
05692 }
05693
05694 PrintMatToDebug( "P", m_RTKDD.P );
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709
05710
05711
05712
05713
05714
05715 }
05716
05717 return true;
05718 }
05719
05720
05721
05722
05723
05724 }
05725
05726
05727