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 <memory.h>
00039 #include <math.h>
00040
00041 #include "GNSS_RxData.h"
00042 #include "novatel.h"
00043 #include "constants.h"
00044 #include "geodesy.h"
00045 #include "Matrix.h"
00046
00047 using namespace Zenautics;
00048
00049
00050 #define GPS_NUMBER_VALID_PRNS (64)
00051
00052 #ifndef SECONDS_IN_DAY
00053 #define SECONDS_IN_DAY (86400.0)
00054 #endif
00055
00056 #ifndef SECONDS_IN_WEEK
00057 #define SECONDS_IN_WEEK (604800.0)
00058 #endif
00059
00060
00061 #ifndef WIN32
00062 #define _CRT_SECURE_NO_DEPRECATE
00063 #endif
00064
00065
00066 namespace GNSS
00067 {
00068
00069 GPS_BroadcastEphemerisAndAlmanacArray::GPS_BroadcastEphemerisAndAlmanacArray()
00070 : m_array(NULL),
00071 m_arrayLength(0)
00072 {
00073 }
00074
00075
00076 GPS_BroadcastEphemerisAndAlmanacArray::~GPS_BroadcastEphemerisAndAlmanacArray()
00077 {
00078 if( m_array != NULL )
00079 {
00080 delete[] m_array;
00081 m_arrayLength = 0;
00082 }
00083 }
00084
00085 bool GPS_BroadcastEphemerisAndAlmanacArray::AllocateArray()
00086 {
00087 unsigned i = 0;
00088 if( m_array != NULL )
00089 {
00090 if( m_arrayLength == GPS_NUMBER_VALID_PRNS )
00091 return true;
00092 else
00093 return false;
00094 }
00095 m_array = new GPS_structOrbitParameters[GPS_NUMBER_VALID_PRNS];
00096 if( m_array == NULL )
00097 return false;
00098 m_arrayLength = GPS_NUMBER_VALID_PRNS;
00099
00100
00101 for( i = 0; i < GPS_NUMBER_VALID_PRNS; i++ )
00102 {
00103 memset( &m_array[i], 0, sizeof(GPS_structOrbitParameters) );
00104 }
00105
00106 return true;
00107 }
00108
00109
00110 bool GPS_BroadcastEphemerisAndAlmanacArray::AddEphemeris( const unsigned short prn, const GPS_structEphemeris &eph )
00111 {
00112 unsigned short index = 0;
00113
00114 if( m_arrayLength == 0 )
00115 {
00116 if( !AllocateArray() )
00117 return false;
00118 }
00119
00120 if( !GetIndexGivenPRN( prn, index ) )
00121 return false;
00122
00123
00124 m_array[index].previousEph = m_array[index].currentEph;
00125 m_array[index].currentEph = eph;
00126
00127 return true;
00128 }
00129
00130 bool GPS_BroadcastEphemerisAndAlmanacArray::AddAlmanac( const unsigned short prn, const GPS_structAlmanac &alm )
00131 {
00132 unsigned short index = 0;
00133
00134 if( m_arrayLength == 0 )
00135 {
00136 if( !AllocateArray() )
00137 return false;
00138 }
00139
00140 if( !GetIndexGivenPRN( prn, index ) )
00141 return false;
00142
00143 m_array[index].almanac = alm;
00144
00145 return true;
00146 }
00147
00148 bool GPS_BroadcastEphemerisAndAlmanacArray::GetEphemeris(
00149 const unsigned short prn,
00150 GPS_structEphemeris &eph,
00151 bool &isAvailable,
00152 char iode
00153 )
00154 {
00155 unsigned short index = 0;
00156
00157 if( m_arrayLength == 0 )
00158 {
00159 isAvailable = false;
00160 return true;
00161 }
00162
00163 if( !GetIndexGivenPRN( prn, index ) )
00164 return false;
00165
00166
00167 if( m_array[index].currentEph.prn == 0 )
00168 {
00169 isAvailable = false;
00170 return true;
00171 }
00172
00173 isAvailable = true;
00174 if( iode == -1 )
00175 {
00176 eph = m_array[index].currentEph;
00177 }
00178 else
00179 {
00180 if( m_array[index].currentEph.iode == iode )
00181 {
00182 eph = m_array[index].currentEph;
00183 }
00184 else if( m_array[index].previousEph.iode == iode )
00185 {
00186 eph = m_array[index].previousEph;
00187 }
00188 else
00189 {
00190 isAvailable = false;
00191 }
00192 }
00193 return true;
00194 }
00195
00196 bool GPS_BroadcastEphemerisAndAlmanacArray::GetEphemerisTOW(
00197 const unsigned short prn,
00198 bool &isAvailable,
00199 unsigned short &week,
00200 unsigned &tow
00201 )
00202 {
00203 unsigned short index = 0;
00204 unsigned short eph_week = 0;
00205 int eph_toe = 0;
00206 int eph_tow = 0;
00207
00208 if( m_arrayLength == 0 )
00209 {
00210 isAvailable = false;
00211 return true;
00212 }
00213
00214 if( !GetIndexGivenPRN( prn, index ) )
00215 return false;
00216
00217
00218 if( m_array[index].currentEph.prn == 0 )
00219 {
00220 isAvailable = false;
00221 return true;
00222 }
00223
00224 isAvailable = true;
00225 if( isAvailable )
00226 {
00227 eph_toe = (int)m_array[index].currentEph.toe;
00228 eph_week = m_array[index].currentEph.week;
00229 eph_tow = (int)m_array[index].currentEph.tow;
00230
00231
00232
00233
00234 if( (eph_tow - eph_toe) < (-4*86400) )
00235 {
00236 eph_week++;
00237 }
00238
00239 week = eph_week;
00240 tow = eph_tow;
00241 }
00242 else
00243 {
00244 week = 0;
00245 tow = 0;
00246 }
00247 return true;
00248
00249 }
00250
00251 bool GPS_BroadcastEphemerisAndAlmanacArray::IsEphemerisAvailable(
00252 const unsigned short prn,
00253 bool &isAvailable,
00254 char iode
00255 )
00256 {
00257 unsigned short index = 0;
00258
00259
00260 if( m_arrayLength == 0 )
00261 {
00262 isAvailable = false;
00263 return true;
00264 }
00265
00266 if( !GetIndexGivenPRN( prn, index ) )
00267 return false;
00268
00269
00270 if( m_array[index].currentEph.prn == 0 )
00271 {
00272 isAvailable = false;
00273 return true;
00274 }
00275
00276 if( iode == -1 )
00277 {
00278 isAvailable = true;
00279 }
00280 else
00281 {
00282 if( m_array[index].currentEph.iode == iode )
00283 {
00284 isAvailable = true;
00285 }
00286 else if( m_array[index].previousEph.iode == iode )
00287 {
00288 isAvailable = true;
00289 }
00290 else
00291 {
00292 isAvailable = false;
00293 }
00294 }
00295 return true;
00296 }
00297
00298
00299
00300 bool GPS_BroadcastEphemerisAndAlmanacArray::GetIndexGivenPRN( const unsigned short prn, unsigned short &index )
00301 {
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 if( prn == 0 )
00331 {
00332 return false;
00333 }
00334 if( prn > 38 && prn < 120 )
00335 {
00336 return false;
00337 }
00338 if( prn > 138 )
00339 {
00340 return false;
00341 }
00342
00343 if( prn < 38 )
00344 {
00345 index = prn - 1;
00346 }
00347 if( prn > 119 && prn < 139 )
00348 {
00349 index = prn - 80;
00350 }
00351 return true;
00352 }
00353
00354
00355
00356
00357
00358 GNSS_RxData::GNSS_RxData()
00359 : m_nrValidObs(0),
00360 m_prev_nrValidObs(0),
00361 m_elevationMask(5.0*DEG2RAD),
00362 m_cnoMask(28.0),
00363 m_locktimeMask(0.0),
00364 m_maxAgeEphemeris(14400),
00365 m_DisableTropoCorrection(false),
00366 m_DisableIonoCorrection(false),
00367 m_fid(NULL),
00368 m_messageLength(0),
00369 m_rxDataType(GNSS_RXDATA_UNKNOWN),
00370 m_CheckRinexObservationHeader(false),
00371 m_RINEX_use_eph(false),
00372 m_RINEX_eph_index(0)
00373 {
00374 m_message[0] = '\0';
00375 ZeroAllMeasurements();
00376 ZeroPVT();
00377
00378 memset( &m_klobuchar, 0, sizeof(GNSS_structKlobuchar) );
00379 memset( &m_RINEX_obs_header, 0, sizeof(RINEX_structDecodedHeader) );
00380
00381 m_RINEX_eph.eph_array = NULL;
00382 m_RINEX_eph.array_length = 0;
00383 m_RINEX_eph.max_array_length = 0;
00384 }
00385
00386
00387 GNSS_RxData::~GNSS_RxData()
00388 {
00389 if( m_fid != NULL )
00390 {
00391 fclose( m_fid );
00392 }
00393 if( m_RINEX_eph.eph_array != NULL )
00394 {
00395 delete[] m_RINEX_eph.eph_array;
00396 }
00397 }
00398
00399
00400 bool GNSS_RxData::ZeroAllMeasurements()
00401 {
00402 unsigned i = 0;
00403
00404 m_nrValidObs = 0;
00405
00406 for( i = 0; i < GNSS_RXDATA_NR_CHANNELS; i++ )
00407 {
00408 memset( &(m_ObsArray[i]), 0, sizeof(GNSS_structMeasurement) );
00409 memset( &(m_prev_ObsArray[i]), 0, sizeof(GNSS_structMeasurement) );
00410 }
00411 return true;
00412 }
00413
00414
00415 bool GNSS_RxData::ZeroPVT()
00416 {
00417 memset( &m_pvt, 0, sizeof(GNSS_structPVT) );
00418 memset( &m_prev_pvt, 0, sizeof(GNSS_structPVT) );
00419 return true;
00420 }
00421
00422
00423 bool GNSS_RxData::Initialize(
00424 const char* path,
00425 bool &isValidPath,
00426 const GNSS_enumRxDataType rxType,
00427 const char* RINEX_ephemeris_path
00428 )
00429 {
00430 bool isRinexValid = false;
00431 isValidPath = false;
00432
00433 if( path == NULL )
00434 {
00435 return false;
00436 }
00437 if( rxType == GNSS_RXDATA_UNKNOWN )
00438 {
00439 return false;
00440 }
00441
00442 m_rxDataType = rxType;
00443
00444 if( rxType == GNSS_RXDATA_RINEX21 || rxType == GNSS_RXDATA_RINEX211 )
00445 {
00446 if( !CheckRINEXObservationHeader( path, isRinexValid ) )
00447 return false;
00448 if( !isRinexValid )
00449 return false;
00450 }
00451
00452 if( RINEX_ephemeris_path != NULL )
00453 {
00454 m_RINEX_eph.filepath = RINEX_ephemeris_path;
00455
00456 if( !LoadRINEXNavigationData() )
00457 return false;
00458
00459
00460 m_RINEX_use_eph = true;
00461 }
00462
00463 #ifndef _CRT_SECURE_NO_DEPRECATE
00464 if( fopen_s( &m_fid, path, "rb" ) != 0 )
00465 return false;
00466 #else
00467 m_fid = fopen( path, "rb" );
00468 #endif
00469 if( m_fid == NULL )
00470 return false;
00471
00472
00473 if( rxType == GNSS_RXDATA_RINEX21 || rxType == GNSS_RXDATA_RINEX211 )
00474 {
00475
00476 while( !feof(m_fid) && ferror(m_fid)==0 )
00477 {
00478 if( fgets( (char*)m_message, GNSS_RXDATA_MSG_LENGTH, m_fid ) == NULL )
00479 break;
00480 if( strstr( (char*)m_message, "END OF HEADER" ) != NULL )
00481 break;
00482 }
00483 }
00484
00485 if( feof(m_fid) || ferror(m_fid) != 0 )
00486 {
00487 if( m_fid != NULL )
00488 fclose(m_fid);
00489 return false;
00490 }
00491
00492 isValidPath = true;
00493
00494 return true;
00495 }
00496
00497 bool GNSS_RxData::LoadNext( bool &endOfStream )
00498 {
00499 bool result = false;
00500 switch( m_rxDataType )
00501 {
00502 case GNSS_RXDATA_NOVATELOEM4:
00503 {
00504 result = LoadNext_NOVATELOEM4( endOfStream );
00505 break;
00506 }
00507 case GNSS_RXDATA_RINEX21:
00508 {
00509 result = LoadNext_RINEX21( endOfStream );
00510 break;
00511 }
00512 case GNSS_RXDATA_RINEX211:
00513 {
00514 result = LoadNext_RINEX211( endOfStream );
00515 break;
00516 }
00517 default:
00518 {
00519 return false;
00520 break;
00521 }
00522 }
00523
00524 if( result )
00525 {
00526 if( m_RINEX_use_eph )
00527 {
00528 if( !UpdateTheEphemerisArrayWithUsingRINEX() )
00529 return false;
00530 }
00531 }
00532 return result;
00533 }
00534
00535 bool GNSS_RxData::CheckRINEXObservationHeader( const char *filepath, bool &isValid )
00536 {
00537 BOOL result;
00538 char RINEX_buffer[16384];
00539 unsigned RINEX_buffer_size = 0;
00540 double version = 0.0;
00541 RINEX_enumFileType file_type = RINEX_FILE_TYPE_UNKNOWN;
00542
00543 isValid = false;
00544
00545 if( filepath == NULL )
00546 return false;
00547
00548 result = RINEX_GetHeader(
00549 filepath,
00550 RINEX_buffer,
00551 16384,
00552 &RINEX_buffer_size,
00553 &version,
00554 &file_type
00555 );
00556 if( result == FALSE )
00557 return false;
00558
00559 result = RINEX_DecodeHeader_ObservationFile(
00560 RINEX_buffer,
00561 RINEX_buffer_size,
00562 &m_RINEX_obs_header
00563 );
00564 if( result == FALSE )
00565 return false;
00566
00567 if( file_type != RINEX_FILE_TYPE_OBS )
00568 {
00569 isValid = false;
00570 return true;
00571 }
00572
00573 if( m_rxDataType == GNSS_RXDATA_RINEX21 )
00574 {
00575 if( fabs( version - 2.1 ) < 1e-02 )
00576 isValid = true;
00577 }
00578 else if( m_rxDataType == GNSS_RXDATA_RINEX211 )
00579 {
00580 if( fabs( version - 2.11 ) < 1e-03 )
00581 isValid = true;
00582 }
00583 else
00584 {
00585 isValid = false;
00586 }
00587 return true;
00588 }
00589
00590 bool GNSS_RxData::LoadNext_RINEX21( bool &endOfStream )
00591 {
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 return true;
00604 }
00605
00606 bool GNSS_RxData::LoadNext_RINEX211( bool &endOfStream )
00607 {
00608 BOOL result=0;
00609 unsigned i = 0;
00610 unsigned j = 0;
00611 unsigned short rx_gps_week = 0;
00612 double rx_gps_tow = 0.0;
00613
00614 BOOL wasEndOfFileReached=0;
00615 BOOL wasObservationFound=0;
00616 unsigned filePosition=0;
00617 unsigned nrObs = 0;
00618 bool isAvailable = false;
00619
00620 endOfStream = false;
00621
00622 if( m_fid == NULL )
00623 return false;
00624
00625
00626 m_prev_nrValidObs = m_nrValidObs;
00627 for( i = 0; i < m_nrValidObs; i++ )
00628 {
00629 m_prev_ObsArray[i] = m_ObsArray[i];
00630 memset( &(m_ObsArray[i]), 0, sizeof(GNSS_structMeasurement) );
00631 }
00632
00633
00634 result = RINEX_GetNextObservationSet(
00635 m_fid,
00636 &m_RINEX_obs_header,
00637 &wasEndOfFileReached,
00638 &wasObservationFound,
00639 &filePosition,
00640 m_ObsArray,
00641 GNSS_RXDATA_NR_CHANNELS,
00642 &nrObs,
00643 &rx_gps_week,
00644 &rx_gps_tow
00645 );
00646 if( result == FALSE )
00647 return false;
00648
00649 if( wasEndOfFileReached )
00650 {
00651 endOfStream = true;
00652 return true;
00653 }
00654
00655 m_nrGPSL1Obs = 0;
00656 m_nrValidObs = 0;
00657 if( nrObs > 0 )
00658 {
00659
00660 m_pvt.time.gps_week = rx_gps_week;
00661 m_pvt.time.gps_tow = rx_gps_tow;
00662
00663 for(i = 0; i < nrObs; i++ )
00664 {
00665 m_ObsArray[i].stdev_psr = 1.4f;
00666 m_ObsArray[i].stdev_adr = 0.05f;
00667 m_ObsArray[i].stdev_doppler = 0.5f;
00668
00669
00670 if( !m_EphAlmArray.IsEphemerisAvailable( m_ObsArray[i].id, isAvailable ) )
00671 return false;
00672 m_ObsArray[i].flags.isEphemerisValid = isAvailable;
00673
00674 if( m_DisableTropoCorrection )
00675 m_ObsArray[i].flags.useTropoCorrection = 0;
00676 else
00677 m_ObsArray[i].flags.useTropoCorrection = 1;
00678
00679 if( m_DisableIonoCorrection )
00680 m_ObsArray[i].flags.useBroadcastIonoCorrection = 0;
00681 else
00682 m_ObsArray[i].flags.useBroadcastIonoCorrection = 1;
00683
00684 if( m_ObsArray[i].system == GNSS_GPS &&
00685 m_ObsArray[i].freqType == GNSS_GPSL1 )
00686 {
00687 m_nrGPSL1Obs++;
00688 }
00689 m_nrValidObs++;
00690 }
00691 }
00692
00693
00694
00695
00696 for( i = 0; i < m_nrValidObs; i++ )
00697 {
00698 for( j = 0; j < m_prev_nrValidObs; j++ )
00699 {
00700 if( m_ObsArray[i].codeType == m_prev_ObsArray[j].codeType &&
00701 m_ObsArray[i].freqType == m_prev_ObsArray[j].freqType &&
00702 m_ObsArray[i].system == m_prev_ObsArray[j].system &&
00703 m_ObsArray[i].id == m_prev_ObsArray[j].id )
00704 {
00705 m_ObsArray[i].ambiguity = m_prev_ObsArray[j].ambiguity;
00706 break;
00707 }
00708 }
00709 }
00710
00711 return true;
00712 }
00713
00714 bool GNSS_RxData::LoadNext_NOVATELOEM4( bool &endOfStream )
00715 {
00716 BOOL result = FALSE;
00717 BOOL wasEndOfFileReached = FALSE;
00718 BOOL wasMessageFound = FALSE;
00719 unsigned filePosition = 0;
00720 unsigned short messageID = 0;
00721 NOVATELOEM4_enumMessageType messageType;
00722 unsigned numberBadCRC = 0;
00723
00724
00725 NOVATELOEM4_structBinaryHeader header;
00726
00727
00728 NOVATELOEM4_structObservation obsArray[GNSS_RXDATA_NR_CHANNELS];
00729
00730
00731 GPS_structEphemeris eph;
00732 unsigned prn;
00733 unsigned reference_week;
00734 unsigned reference_tow;
00735 unsigned tow;
00736
00737 unsigned nrValidObs;
00738 unsigned i = 0;
00739 unsigned j = 0;
00740 bool isAvailable;
00741
00742
00743 endOfStream = false;
00744
00745 if( m_fid == NULL )
00746 return false;
00747
00748
00749 m_prev_nrValidObs = m_nrValidObs;
00750 for( i = 0; i < m_nrValidObs; i++ )
00751 {
00752 m_prev_ObsArray[i] = m_ObsArray[i];
00753 memset( &(m_ObsArray[i]), 0, sizeof(GNSS_structMeasurement) );
00754 }
00755
00756 switch( m_rxDataType )
00757 {
00758 case GNSS_RXDATA_NOVATELOEM4:
00759 {
00760 while( !wasEndOfFileReached && !wasMessageFound )
00761 {
00762 result = NOVATELOEM4_FindNextMessageInFile(
00763 m_fid,
00764 m_message,
00765 GNSS_RXDATA_MSG_LENGTH,
00766 &wasEndOfFileReached,
00767 &wasMessageFound,
00768 &filePosition,
00769 &m_messageLength,
00770 &messageID,
00771 &numberBadCRC
00772 );
00773 if( result == FALSE )
00774 return false;
00775
00776 messageType = (NOVATELOEM4_enumMessageType)messageID;
00777 if( wasMessageFound && messageType != NOVATELOEM4_RANGEB )
00778 {
00779 if( messageType == NOVATELOEM4_RAWEPHEMB )
00780 {
00781 memset( &eph, 0, sizeof(GPS_structEphemeris) );
00782
00783 result = NOVATELOEM4_DecodeRAWEPHEMB(
00784 m_message,
00785 m_messageLength,
00786 &header,
00787 &prn,
00788 &reference_week,
00789 &reference_tow,
00790 &tow,
00791 &eph.iodc,
00792 &eph.iode,
00793 &eph.toe,
00794 &eph.toc,
00795 &eph.week,
00796 &eph.health,
00797 &eph.alert_flag,
00798 &eph.anti_spoof,
00799 &eph.code_on_L2,
00800 &eph.ura,
00801 &eph.L2_P_data_flag,
00802 &eph.fit_interval_flag,
00803 &eph.age_of_data_offset,
00804 &eph.tgd,
00805 &eph.af2,
00806 &eph.af1,
00807 &eph.af0,
00808 &eph.m0,
00809 &eph.delta_n,
00810 &eph.ecc,
00811 &eph.sqrta,
00812 &eph.omega0,
00813 &eph.i0,
00814 &eph.w,
00815 &eph.omegadot,
00816 &eph.idot,
00817 &eph.cuc,
00818 &eph.cus,
00819 &eph.crc,
00820 &eph.crs,
00821 &eph.cic,
00822 &eph.cis );
00823 if( result )
00824 {
00825 eph.prn = prn;
00826
00827 result = m_EphAlmArray.AddEphemeris( eph.prn, eph );
00828 if( !result )
00829 {
00830
00831 return false;
00832 }
00833 }
00834 }
00835 wasMessageFound = false;
00836 }
00837 }
00838 if( wasMessageFound && messageType == NOVATELOEM4_RANGEB )
00839 {
00840 m_nrValidObs = 0;
00841 m_nrGPSL1Obs = 0;
00842
00843 result = NOVATELOEM4_DecodeRANGEB(
00844 m_message,
00845 m_messageLength,
00846 &header,
00847 obsArray,
00848 GNSS_RXDATA_NR_CHANNELS,
00849 &nrValidObs
00850 );
00851 if( result == FALSE )
00852 return false;
00853
00854
00855 m_pvt.time.gps_week = header.gpsWeek;
00856 m_pvt.time.gps_tow = header.gpsMilliSeconds / 1000.0;
00857
00858 for( i = 0; i < nrValidObs && i < GNSS_RXDATA_NR_CHANNELS; i++ )
00859 {
00860 m_ObsArray[i].channel = obsArray[i].trackingStatus.channelNumber;
00861 m_ObsArray[i].id = obsArray[i].prn;
00862
00863 m_ObsArray[i].system = (GNSS_enumSystem)obsArray[i].trackingStatus.eSatelliteSystem;
00864 m_ObsArray[i].codeType = (GNSS_enumCodeType)obsArray[i].trackingStatus.eCodeType;
00865 m_ObsArray[i].freqType = (GNSS_enumFrequency)obsArray[i].trackingStatus.eFrequency;
00866
00867 if( m_ObsArray[i].system == GNSS_GPS &&
00868 m_ObsArray[i].freqType == GNSS_GPSL1 )
00869 {
00870 m_nrGPSL1Obs++;
00871 }
00872
00873 m_ObsArray[i].psr = obsArray[i].psr;
00874 m_ObsArray[i].adr = -1.0*obsArray[i].adr;
00875 m_ObsArray[i].doppler = obsArray[i].doppler;
00876 m_ObsArray[i].cno = obsArray[i].cno;
00877 m_ObsArray[i].locktime = obsArray[i].locktime;
00878
00879 if( obsArray[i].psrstd < 0.2 )
00880 m_ObsArray[i].stdev_psr = 0.2f;
00881 else
00882 m_ObsArray[i].stdev_psr = obsArray[i].psrstd;
00883
00884 m_ObsArray[i].stdev_psr = 1.4f;
00885
00886 if( obsArray[i].adrstd < 0.0025 )
00887 m_ObsArray[i].stdev_adr = 0.0025f;
00888 else
00889 m_ObsArray[i].stdev_adr = obsArray[i].adrstd;
00890
00891 if( obsArray[i].adrstd < 0.0001 )
00892 int gaa = 99;
00893
00894 m_ObsArray[i].stdev_adr = 0.05f;
00895
00896 m_ObsArray[i].stdev_doppler = 0.5f;
00897
00898 m_ObsArray[i].psr_smoothed = 0.0;
00899 m_ObsArray[i].psr_predicted = 0.0;
00900 m_ObsArray[i].doppler_predicted = 0.0;
00901 m_ObsArray[i].azimuthRads = 0.0;
00902 m_ObsArray[i].elevationRads = 0.0;
00903
00904 m_ObsArray[i].flags.isActive = 1;
00905 m_ObsArray[i].flags.isCodeLocked = obsArray[i].trackingStatus.isCodeLocked;
00906 m_ObsArray[i].flags.isPhaseLocked = obsArray[i].trackingStatus.isPhaseLocked;
00907 m_ObsArray[i].flags.isParityValid = obsArray[i].trackingStatus.isParityKnown;
00908 m_ObsArray[i].flags.isPsrValid = obsArray[i].trackingStatus.isCodeLocked;
00909 m_ObsArray[i].flags.isAdrValid = obsArray[i].trackingStatus.isPhaseLocked & obsArray[i].trackingStatus.isParityKnown;
00910 m_ObsArray[i].flags.isDopplerValid = obsArray[i].trackingStatus.isCodeLocked;
00911 m_ObsArray[i].flags.isGrouped = obsArray[i].trackingStatus.isGrouped;
00912 m_ObsArray[i].flags.isAutoAssigned = !obsArray[i].trackingStatus.isForcedAssignment;
00913 m_ObsArray[i].flags.isCarrierSmoothed = 0;
00914
00915
00916 if( !m_EphAlmArray.IsEphemerisAvailable( m_ObsArray[i].id, isAvailable ) )
00917 return false;
00918
00919 m_ObsArray[i].flags.isEphemerisValid = isAvailable;
00920
00921 m_ObsArray[i].flags.isAlmanacValid = 0;
00922 m_ObsArray[i].flags.isAboveElevationMask = 0;
00923 m_ObsArray[i].flags.isAboveCNoMask = 0;
00924 m_ObsArray[i].flags.isAboveLockTimeMask = 0;
00925 m_ObsArray[i].flags.isNotUserRejected = 1;
00926 m_ObsArray[i].flags.isNotPsrRejected = 1;
00927 m_ObsArray[i].flags.isNotAdrRejected = 1;
00928 m_ObsArray[i].flags.isNotDopplerRejected = 1;
00929 m_ObsArray[i].flags.isNoCycleSlipDetected = 1;
00930 m_ObsArray[i].flags.isPsrUsedInSolution = 0;
00931 m_ObsArray[i].flags.isDopplerUsedInSolution = 0;
00932 m_ObsArray[i].flags.isAdrUsedInSolution = 0;
00933
00934 if( m_DisableTropoCorrection )
00935 m_ObsArray[i].flags.useTropoCorrection = 0;
00936 else
00937 m_ObsArray[i].flags.useTropoCorrection = 1;
00938
00939 if( m_DisableIonoCorrection )
00940 m_ObsArray[i].flags.useBroadcastIonoCorrection = 0;
00941 else
00942 m_ObsArray[i].flags.useBroadcastIonoCorrection = 1;
00943
00944 m_ObsArray[i].corrections.prcTropoDry = 0;
00945 m_ObsArray[i].corrections.prcTropoWet = 0;
00946 m_ObsArray[i].corrections.prcIono = 0;
00947 m_ObsArray[i].corrections.prcSatClk = 0;
00948 m_ObsArray[i].corrections.prcReserved1 = 0;
00949 m_ObsArray[i].corrections.prcReserved2 = 0;
00950 m_ObsArray[i].corrections.rrcSatClkDrift = 0;
00951 m_ObsArray[i].corrections.rrcReserved1 = 0;
00952 m_ObsArray[i].corrections.rrcReserved2 = 0;
00953 m_ObsArray[i].corrections.dX = 0;
00954 m_ObsArray[i].corrections.dY = 0;
00955 m_ObsArray[i].corrections.dZ = 0;
00956
00957 m_ObsArray[i].residuals.psrResidual = 0;
00958 m_ObsArray[i].residuals.adrResidual = 0;
00959 m_ObsArray[i].residuals.dopplerResidual = 0;
00960 m_ObsArray[i].residuals.reserved = 0;
00961
00962 m_nrValidObs++;
00963 }
00964
00965 }
00966 if( wasEndOfFileReached )
00967 {
00968 endOfStream = true;
00969 }
00970 break;
00971 }
00972 default:
00973 {
00974 return false;
00975 }
00976 }
00977
00978
00979
00980
00981 for( i = 0; i < m_nrValidObs; i++ )
00982 {
00983 for( j = 0; j < m_prev_nrValidObs; j++ )
00984 {
00985 if( m_ObsArray[i].codeType == m_prev_ObsArray[j].codeType &&
00986 m_ObsArray[i].freqType == m_prev_ObsArray[j].freqType &&
00987 m_ObsArray[i].system == m_prev_ObsArray[j].system &&
00988 m_ObsArray[i].id == m_prev_ObsArray[j].id )
00989 {
00990 m_ObsArray[i].ambiguity = m_prev_ObsArray[j].ambiguity;
00991 break;
00992 }
00993 }
00994 }
00995
00996
00997 return true;
00998 }
00999
01000 bool GNSS_RxData::SetInitialPVT(
01001 const double latitudeRads,
01002 const double longitudeRads,
01003 const double height,
01004 const double vn,
01005 const double ve,
01006 const double vup,
01007 const double clk,
01008 const double clkdrift,
01009 const double std_lat,
01010 const double std_lon,
01011 const double std_hgt,
01012 const double std_vn,
01013 const double std_ve,
01014 const double std_vup,
01015 const double std_clk,
01016 const double std_clkdrift,
01017 const double undulation
01018 )
01019 {
01020 bool result;
01021
01022 result = UpdatePositionAndRxClock(
01023 latitudeRads,
01024 longitudeRads,
01025 height,
01026 clk,
01027 std_lat,
01028 std_lon,
01029 std_hgt,
01030 std_clk );
01031 if( !result )
01032 return false;
01033
01034 result = UpdateVelocityAndClockDrift(
01035 vn,
01036 ve,
01037 vup,
01038 clkdrift,
01039 std_vn,
01040 std_ve,
01041 std_vup,
01042 std_clkdrift );
01043 if( !result )
01044 return false;
01045
01046
01047
01048 if( std_lat == 0.0 && std_lon == 0.0 && std_hgt == 0.0 )
01049 {
01050 m_pvt.std_lat = 1e-03;
01051 m_pvt.std_lon = 1e-03;
01052 m_pvt.std_hgt = 1e-03;
01053 m_pvt.isPositionConstrained = 1;
01054 }
01055
01056 m_pvt.isHeightConstrained = 0;
01057 m_pvt.isClockConstrained = 0;
01058 m_pvt.isSolutionBasedOnEphemeris = 0;
01059
01060 m_pvt.undulation = undulation;
01061
01062
01063 m_prev_pvt = m_pvt;
01064
01065 return true;
01066 }
01067
01068
01069 bool GNSS_RxData::UpdatePositionAndRxClock(
01070 const double latitudeRads,
01071 const double longitudeRads,
01072 const double height,
01073 const double clk,
01074 const double std_lat,
01075 const double std_lon,
01076 const double std_hgt,
01077 const double std_clk
01078 )
01079 {
01080 bool result;
01081 m_pvt.latitude = latitudeRads;
01082 m_pvt.longitude = longitudeRads;
01083 m_pvt.height = height;
01084
01085 m_pvt.latitudeDegs = latitudeRads*RAD2DEG;
01086 m_pvt.longitudeDegs = longitudeRads*RAD2DEG;
01087
01088 result = GetDMS(
01089 m_pvt.latitudeDegs,
01090 m_pvt.lat_dms.degrees,
01091 m_pvt.lat_dms.minutes,
01092 m_pvt.lat_dms.seconds,
01093 (char*)m_pvt.lat_dms.dms_str, 24 );
01094 if( result == false )
01095 return false;
01096
01097 result = GetDMS(
01098 m_pvt.longitudeDegs,
01099 m_pvt.lon_dms.degrees,
01100 m_pvt.lon_dms.minutes,
01101 m_pvt.lon_dms.seconds,
01102 (char*)m_pvt.lon_dms.dms_str, 24 );
01103 if( result == false )
01104 return false;
01105
01106 if( GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
01107 GEODESY_REFERENCE_ELLIPSE_WGS84,
01108 m_pvt.latitude,
01109 m_pvt.longitude,
01110 m_pvt.height,
01111 &m_pvt.x,
01112 &m_pvt.y,
01113 &m_pvt.z ) == FALSE )
01114 {
01115 return false;
01116 }
01117 m_pvt.clockOffset = clk;
01118
01119 m_pvt.std_lat = std_lat;
01120 m_pvt.std_lon = std_lon;
01121 m_pvt.std_hgt = std_hgt;
01122 m_pvt.std_clk = std_clk;
01123
01124 return true;
01125 }
01126
01127 bool GNSS_RxData::UpdateVelocityAndClockDrift(
01128 const double vn,
01129 const double ve,
01130 const double vup,
01131 const double clkdrift,
01132 const double std_vn,
01133 const double std_ve,
01134 const double std_vup,
01135 const double std_clkdrift
01136 )
01137 {
01138 m_pvt.vn = vn;
01139 m_pvt.ve = ve;
01140 m_pvt.vup = vup;
01141
01142 GEODESY_RotateVectorFromLocalGeodeticFrameToEarthFixedFrame(
01143 m_pvt.latitude,
01144 m_pvt.longitude,
01145 m_pvt.vn,
01146 m_pvt.ve,
01147 m_pvt.vup,
01148 &m_pvt.vx,
01149 &m_pvt.vy,
01150 &m_pvt.vz );
01151
01152 m_pvt.clockDrift = clkdrift;
01153
01154 m_pvt.std_vn = std_vn;
01155 m_pvt.std_ve = std_ve;
01156 m_pvt.std_vup = std_vup;
01157 m_pvt.std_clkdrift = std_clkdrift;
01158
01159 return true;
01160 }
01161
01162
01163
01164
01165 bool GNSS_RxData::GetDMS(
01166 const double angleDegs,
01167 short °rees,
01168 short &minutes,
01169 float &seconds,
01170 char *dms_str,
01171 const unsigned maxLength_dms_str
01172 )
01173 {
01174 bool isNegative = false;
01175 double angle = angleDegs;
01176 int result = 0;
01177
01178 if( angleDegs < 0 )
01179 {
01180 isNegative = true;
01181 angle = -angleDegs;
01182 }
01183 else
01184 {
01185 angle = angleDegs;
01186 }
01187
01188 degrees = static_cast<short>(floor(angle));
01189 minutes = static_cast<short>(floor((angle - degrees)*60.0));
01190 seconds = static_cast<float>((angle - degrees - minutes/60.0)*3600.0);
01191
01192 if( isNegative )
01193 degrees = -degrees;
01194
01195 #ifndef _CRT_SECURE_NO_DEPRECATE
01196 result = sprintf_s(
01197 dms_str,
01198 maxLength_dms_str,
01199 "%+4d%c%02d\'%02.4f\"",
01200 degrees,
01201 176,
01202 minutes,
01203 seconds );
01204 #else
01205 result = sprintf(
01206 dms_str,
01207 "%+4d%c%02d\'%02.4f\"",
01208 degrees,
01209 176,
01210 minutes,
01211 seconds );
01212 #endif
01213
01214 if( result == -1 )
01215 return false;
01216
01217 return true;
01218 }
01219
01220
01221 bool GNSS_RxData::CheckForCycleSlips_UsingPhaseRatePrediction(
01222 const double nrThresholdCycles
01223 )
01224 {
01225 unsigned i = 0;
01226 unsigned j = 0;
01227 double t_prev = 0.0;
01228 double t = 0.0;
01229 double dt = 0.0;
01230 double phase_diff = 0.0;
01231 double predicted_phase = 0.0;
01232 double mean_doppler = 0.0;
01233
01234 static double max_dif = 0.0;
01235
01236 t_prev = m_prev_pvt.time.gps_week*SECONDS_IN_WEEK + m_prev_pvt.time.gps_tow;
01237 t = m_pvt.time.gps_week*SECONDS_IN_WEEK + m_pvt.time.gps_tow;
01238 dt = t - t_prev;
01239 if( dt <= 0.0 )
01240 {
01241 return false;
01242 }
01243 if( dt > 60.0 )
01244 {
01245 return true;
01246 }
01247
01248 for( i = 0; i < m_nrValidObs; i++ )
01249 {
01250 for( j = 0; j < m_prev_nrValidObs; j++ )
01251 {
01252 if( m_ObsArray[i].system == m_prev_ObsArray[j].system &&
01253 m_ObsArray[i].id == m_prev_ObsArray[j].id &&
01254 m_ObsArray[i].freqType == m_prev_ObsArray[j].freqType )
01255 {
01256
01257
01258
01259
01260 if( m_ObsArray[i].flags.isPhaseLocked && m_prev_ObsArray[j].flags.isPhaseLocked )
01261 {
01262 mean_doppler = (m_ObsArray[i].doppler + m_prev_ObsArray[j].doppler)/2.0;
01263
01264 predicted_phase = m_prev_ObsArray[j].adr - mean_doppler * dt;
01265
01266 phase_diff = predicted_phase - m_ObsArray[i].adr;
01267
01268 if( fabs(phase_diff) > max_dif )
01269 max_dif = fabs(phase_diff);
01270 if( fabs(phase_diff) > nrThresholdCycles )
01271 {
01272 m_ObsArray[i].flags.isNoCycleSlipDetected = 0;
01273 }
01274 else
01275 {
01276 m_ObsArray[i].flags.isNoCycleSlipDetected = 1;
01277 }
01278 break;
01279 }
01280 }
01281 }
01282 }
01283
01284 return true;
01285 }
01286
01287
01288 bool GNSS_RxData::DebugPrintObservationArray( const char *filepath )
01289 {
01290 unsigned i = 0;
01291 unsigned j = 0;
01292 Matrix X(100,m_nrValidObs);
01293
01294 if( filepath == NULL )
01295 return false;
01296
01297
01298 for( i = 0; i < m_nrValidObs; i++ )
01299 {
01300 j = 0;
01301 X[j][i] = m_ObsArray[i].channel; j++;
01302 X[j][i] = m_ObsArray[i].id; j++;
01303 X[j][i] = m_ObsArray[i].system; j++;
01304 X[j][i] = m_ObsArray[i].codeType; j++;
01305 X[j][i] = m_ObsArray[i].freqType; j++;
01306
01307 X[j][i] = m_ObsArray[i].flags.isActive; j++;
01308 X[j][i] = m_ObsArray[i].flags.isCodeLocked; j++;
01309 X[j][i] = m_ObsArray[i].flags.isPhaseLocked; j++;
01310 X[j][i] = m_ObsArray[i].flags.isParityValid; j++;
01311 X[j][i] = m_ObsArray[i].flags.isPsrValid; j++;
01312 X[j][i] = m_ObsArray[i].flags.isAdrValid; j++;
01313 X[j][i] = m_ObsArray[i].flags.isDopplerValid; j++;
01314 X[j][i] = m_ObsArray[i].flags.isGrouped; j++;
01315 X[j][i] = m_ObsArray[i].flags.isAutoAssigned; j++;
01316 X[j][i] = m_ObsArray[i].flags.isCarrierSmoothed; j++;
01317 X[j][i] = m_ObsArray[i].flags.isEphemerisValid; j++;
01318 X[j][i] = m_ObsArray[i].flags.isAlmanacValid; j++;
01319 X[j][i] = m_ObsArray[i].flags.isAboveElevationMask; j++;
01320 X[j][i] = m_ObsArray[i].flags.isAboveCNoMask; j++;
01321 X[j][i] = m_ObsArray[i].flags.isAboveLockTimeMask; j++;
01322 X[j][i] = m_ObsArray[i].flags.isNotUserRejected; j++;
01323 X[j][i] = m_ObsArray[i].flags.isNotPsrRejected; j++;
01324 X[j][i] = m_ObsArray[i].flags.isNotAdrRejected; j++;
01325 X[j][i] = m_ObsArray[i].flags.isNotDopplerRejected; j++;
01326 X[j][i] = m_ObsArray[i].flags.isNoCycleSlipDetected; j++;
01327 X[j][i] = m_ObsArray[i].flags.isPsrUsedInSolution; j++;
01328 X[j][i] = m_ObsArray[i].flags.isDopplerUsedInSolution; j++;
01329 X[j][i] = m_ObsArray[i].flags.isAdrUsedInSolution; j++;
01330 X[j][i] = m_ObsArray[i].flags.isDifferentialPsrAvailable; j++;
01331 X[j][i] = m_ObsArray[i].flags.isDifferentialDopplerAvailable; j++;
01332 X[j][i] = m_ObsArray[i].flags.isDifferentialAdrAvailable; j++;
01333 X[j][i] = m_ObsArray[i].flags.useTropoCorrection; j++;
01334 X[j][i] = m_ObsArray[i].flags.useBroadcastIonoCorrection; j++;
01335 X[j][i] = m_ObsArray[i].flags.isTimeDifferntialPsrAvailable; j++;
01336 X[j][i] = m_ObsArray[i].flags.isTimeDifferntialDopplerAvailable; j++;
01337
01338 X[j][i] = m_ObsArray[i].week; j++;
01339 X[j][i] = m_ObsArray[i].tow; j++;
01340
01341
01342 X[j][i] = m_ObsArray[i].psr; j++;
01343 X[j][i] = m_ObsArray[i].adr; j++;
01344 X[j][i] = m_ObsArray[i].doppler; j++;
01345 X[j][i] = m_ObsArray[i].cno; j++;
01346 X[j][i] = m_ObsArray[i].locktime; j++;
01347
01348
01349 X[j][i] = m_ObsArray[i].stdev_psr; j++;
01350 X[j][i] = m_ObsArray[i].stdev_adr; j++;
01351 X[j][i] = m_ObsArray[i].stdev_doppler; j++;
01352
01353
01354 X[j][i] = m_ObsArray[i].psr_misclosure; j++;
01355 X[j][i] = m_ObsArray[i].doppler_misclosure; j++;
01356 X[j][i] = m_ObsArray[i].range; j++;
01357 X[j][i] = m_ObsArray[i].rangerate; j++;
01358 X[j][i] = m_ObsArray[i].psr_smoothed; j++;
01359 X[j][i] = m_ObsArray[i].psr_predicted; j++;
01360 X[j][i] = m_ObsArray[i].ambiguity; j++;
01361 X[j][i] = m_ObsArray[i].doppler_predicted; j++;
01362 X[j][i] = m_ObsArray[i].azimuthRads; j++;
01363 X[j][i] = m_ObsArray[i].elevationRads; j++;
01364
01365
01366 X[j][i] = m_ObsArray[i].index_differential; j++;
01367 X[j][i] = m_ObsArray[i].index_time_differential; j++;
01368
01369 X[j][i] = m_ObsArray[i].index_ambiguity_state; j++;
01370 X[j][i] = m_ObsArray[i].adr_misclosure; j++;
01371
01372 X[j][i] = m_ObsArray[i].H_p[0]; j++;
01373 X[j][i] = m_ObsArray[i].H_p[1]; j++;
01374 X[j][i] = m_ObsArray[i].H_p[2]; j++;
01375 X[j][i] = m_ObsArray[i].H_v[0]; j++;
01376 X[j][i] = m_ObsArray[i].H_v[1]; j++;
01377 X[j][i] = m_ObsArray[i].H_v[2]; j++;
01378
01379 X[j][i] = m_ObsArray[i].corrections.dX; j++;
01380 X[j][i] = m_ObsArray[i].corrections.dY; j++;
01381 X[j][i] = m_ObsArray[i].corrections.dZ; j++;
01382 X[j][i] = m_ObsArray[i].corrections.prcIono; j++;
01383 X[j][i] = m_ObsArray[i].corrections.prcReserved1; j++;
01384 X[j][i] = m_ObsArray[i].corrections.prcReserved2; j++;
01385 X[j][i] = m_ObsArray[i].corrections.prcSatClk; j++;
01386 X[j][i] = m_ObsArray[i].corrections.prcTropoDry; j++;
01387 X[j][i] = m_ObsArray[i].corrections.prcTropoWet; j++;
01388 X[j][i] = m_ObsArray[i].corrections.rrcReserved1; j++;
01389
01390 X[j][i] = m_ObsArray[i].residuals.psrResidual; j++;
01391 X[j][i] = m_ObsArray[i].residuals.dopplerResidual; j++;
01392 X[j][i] = m_ObsArray[i].residuals.adrResidual; j++;
01393 X[j][i] = m_ObsArray[i].residuals.reserved; j++;
01394 }
01395 X.Redim(j,m_nrValidObs);
01396
01397 X.Print( filepath, 12 );
01398
01399 return true;
01400 }
01401
01402
01403
01404 bool GNSS_RxData::Debug_WriteSuperMsg80CharsWide(
01405 char* buffer,
01406 const unsigned maxBufferLength,
01407 const double referenceLatitude,
01408 const double referenceLongitude,
01409 const double referenceHeight,
01410 unsigned& nrBytesInBuffer )
01411 {
01412 unsigned i = 0;
01413 unsigned j = 0;
01414 int week = -1;
01415 int tmpi = 0;
01416
01417 unsigned scount = 0;
01418
01419 double x = 0;
01420 double y = 0;
01421 double z = 0;
01422
01423 double n_err = 0.0;
01424 double e_err = 0.0;
01425 double up_err = 0.0;
01426 double dtmp = 0.0;
01427 double v_azimuth = 0.0;
01428
01429 if( maxBufferLength < 1024*8 )
01430 {
01431 nrBytesInBuffer = 0;
01432 return false;
01433 }
01434
01435 scount += sprintf( buffer, "\n");
01436 scount += sprintf( buffer+scount, "GPS_Week GPS_TOW(s) DayOfYear UTC_Time\n" );
01437 scount += sprintf( buffer+scount, " %4d", m_pvt.time.gps_week );
01438 scount += sprintf( buffer+scount, "%13.3lf", m_pvt.time.gps_tow );
01439 scount += sprintf( buffer+scount, " %03d", m_pvt.time.day_of_year );
01440 scount += sprintf( buffer+scount, " %04d, %02d, %02d, %02d:%02d:%05.2lf\n",
01441 m_pvt.time.utc_year,
01442 m_pvt.time.utc_month,
01443 m_pvt.time.utc_day,
01444 m_pvt.time.utc_hour,
01445 m_pvt.time.utc_minute,
01446 m_pvt.time.utc_seconds );
01447 scount += sprintf( buffer+scount, "\n" );
01448
01449 scount += sprintf( buffer+scount, " Lat(deg) Long(deg) Height(m) X(m) Y(m) Z(m)\n");
01450 scount += sprintf( buffer+scount, "Estimated:%10.5f %10.5f %10.3f ", m_pvt.latitudeDegs, m_pvt.longitudeDegs, m_pvt.height );
01451 scount += sprintf( buffer+scount, "%12.1lf %11.1lf %11.1lf\n", m_pvt.x, m_pvt.y, m_pvt.z );
01452
01453 if( referenceLatitude == 0 && referenceLongitude == 0 && referenceHeight == 0 )
01454 {
01455 x = y = z = 0;
01456 }
01457 else
01458 {
01459 GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
01460 GEODESY_REFERENCE_ELLIPSE_WGS84,
01461 referenceLatitude,
01462 referenceLongitude,
01463 referenceHeight,
01464 &x,
01465 &y,
01466 &z );
01467 }
01468
01469 scount += sprintf( buffer+scount, "Reference:%10.5f %10.5f %10.3f ", referenceLatitude*RAD2DEG, referenceLongitude*RAD2DEG, referenceHeight );
01470 scount += sprintf( buffer+scount, "%12.1lf %11.1lf %11.1lf\n", x, y, z );
01471
01472 if( x == 0 && y == 0 && z == 0 )
01473 {
01474 n_err = e_err = up_err = 0.0;
01475 }
01476 else
01477 {
01478 GEODESY_ComputePositionDifference(
01479 GEODESY_REFERENCE_ELLIPSE_WGS84,
01480 referenceLatitude,
01481 referenceLongitude,
01482 referenceHeight,
01483 m_pvt.latitude,
01484 m_pvt.longitude,
01485 m_pvt.height,
01486 &n_err,
01487 &e_err,
01488 &up_err
01489 );
01490 }
01491
01492 scount += sprintf( buffer+scount, "Diff(m) :");
01493 if (fabs(n_err) < 1000) scount += sprintf( buffer+scount, " %9.5f", n_err);
01494 else scount += sprintf( buffer+scount, " ");
01495 if (fabs(e_err) < 1000) scount += sprintf( buffer+scount, " %9.5f", e_err);
01496 else scount += sprintf( buffer+scount, " ");
01497 if (fabs(up_err) < 1000) scount += sprintf( buffer+scount, " %9.3f\n\n", up_err );
01498 else scount += sprintf( buffer+scount, " \n\n");
01499
01500 scount += sprintf( buffer+scount, "East(m/s) North(m/s) Up(m/s) Ground_Speed(km/h) Azimuth(deg)\n" );
01501 dtmp = sqrt( m_pvt.ve*m_pvt.ve + m_pvt.vn*m_pvt.vn )*3.6;
01502 v_azimuth = atan2(m_pvt.ve, m_pvt.vn);
01503 scount += sprintf( buffer+scount, "%9.2lf %15.2lf %13.2lf %23.2lf %15.3lf\n",
01504 m_pvt.vn,
01505 m_pvt.ve,
01506 m_pvt.vup,
01507 dtmp,
01508 v_azimuth*RAD2DEG );
01509 scount += sprintf( buffer+scount, "\n" );
01510
01511
01512 scount += sprintf( buffer+scount, "Nr: PSR U / R Doppler U / R ADR U / R HDOP VDOP PDOP TDOP GDOP\n" );
01513 scount += sprintf( buffer+scount, " %3d%3d%4d", m_pvt.nrPsrObsAvailable, m_pvt.nrPsrObsUsed, m_pvt.nrPsrObsRejected );
01514 scount += sprintf( buffer+scount, "%9d%3d%4d", m_pvt.nrDopplerObsAvailable, m_pvt.nrDopplerObsUsed, m_pvt.nrDopplerObsRejected );
01515 scount += sprintf( buffer+scount, "%5d%3d%4d", m_pvt.nrAdrObsAvailable, m_pvt.nrAdrObsUsed, m_pvt.nrAdrObsRejected );
01516 scount += sprintf( buffer+scount, "%8.1lf %6.1lf %6.1lf %6.1lf %6.1lf\n",
01517 m_pvt.dop.hdop,
01518 m_pvt.dop.vdop,
01519 m_pvt.dop.pdop,
01520 m_pvt.dop.tdop,
01521 m_pvt.dop.gdop );
01522 scount += sprintf( buffer+scount, "\n" );
01523
01524 scount += sprintf( buffer+scount, "%2s", "CH" );
01525 scount += sprintf( buffer+scount, "%3s", "ID" );
01526 scount += sprintf( buffer+scount, "%3s", "S" );
01527 scount += sprintf( buffer+scount, "%13s", "PSR" );
01528 scount += sprintf( buffer+scount, "%2s", "U" );
01529 scount += sprintf( buffer+scount, "%9s", "DOPPLER" );
01530 scount += sprintf( buffer+scount, "%2s", "U" );
01531 scount += sprintf( buffer+scount, "%13s", "ADR" );
01532 scount += sprintf( buffer+scount, "%2s", "U" );
01533 scount += sprintf( buffer+scount, "%6s", "E" );
01534 scount += sprintf( buffer+scount, "%7s", "A" );
01535 scount += sprintf( buffer+scount, "%5s", "C/No" );
01536 scount += sprintf( buffer+scount, "%8s", "LOCK" );
01537 scount += sprintf( buffer+scount, "%3s", "SI" );
01538 scount += sprintf( buffer+scount, "\n" );
01539
01540 for( i = 0; i < m_nrValidObs; i++ )
01541 {
01542 if( m_ObsArray[i].flags.isActive && m_ObsArray[i].freqType == GNSS_GPSL1)
01543 {
01544 scount += sprintf( buffer+scount, "%-2d", m_ObsArray[i].channel );
01545 scount += sprintf( buffer+scount, "%3d", m_ObsArray[i].id );
01546 if( m_ObsArray[i].system == GNSS_GPS && m_ObsArray[i].freqType == GNSS_GPSL1 )
01547 {
01548 scount += sprintf( buffer+scount, "%3s", "L1" );
01549 }
01550 else if( m_ObsArray[i].system == GNSS_GPS && m_ObsArray[i].freqType == GNSS_GPSL2 )
01551 {
01552 scount += sprintf( buffer+scount, "%3s", "L2" );
01553 }
01554 else
01555 {
01556 scount += sprintf( buffer+scount, "%3s", "--" );
01557 }
01558 scount += sprintf( buffer+scount, "%13.1lf", m_ObsArray[i].psr );
01559 scount += sprintf( buffer+scount, "%2d", m_ObsArray[i].flags.isPsrUsedInSolution );
01560
01561 scount += sprintf( buffer+scount, "%9.1lf", m_ObsArray[i].doppler );
01562 scount += sprintf( buffer+scount, "%2d", m_ObsArray[i].flags.isDopplerUsedInSolution );
01563
01564 scount += sprintf( buffer+scount, "%13.1lf", m_ObsArray[i].adr );
01565 scount += sprintf( buffer+scount, "%2d", m_ObsArray[i].flags.isAdrUsedInSolution );
01566
01567 scount += sprintf( buffer+scount, "%6.1lf", m_ObsArray[i].satellite.elevation*RAD2DEG );
01568 scount += sprintf( buffer+scount, "%7.1lf", m_ObsArray[i].satellite.azimuth*RAD2DEG );
01569 scount += sprintf( buffer+scount, "%5.1lf", m_ObsArray[i].cno );
01570 scount += sprintf( buffer+scount, "%8.1lf", m_ObsArray[i].locktime );
01571 scount += sprintf( buffer+scount, "%3d", m_ObsArray[i].index_ambiguity_state );
01572 scount += sprintf( buffer+scount, "\n" );
01573 }
01574 }
01575 scount += sprintf( buffer+scount, "\n" );
01576
01577 nrBytesInBuffer = scount;
01578 return true;
01579 }
01580
01581
01582 bool GNSS_RxData::LoadRINEXNavigationData(void)
01583 {
01584
01585
01586 unsigned line_count = 0;
01587 unsigned estimated_nr_eph = 0;
01588 BOOL result = 0;
01589
01590 FILE* fid = NULL;
01591 fid = fopen( m_RINEX_eph.filepath.c_str(), "r" );
01592 if( fid == NULL )
01593 return false;
01594
01595
01596 while( !feof(fid) && ferror(fid)==0 )
01597 {
01598 if( fgets( (char*)m_message, GNSS_RXDATA_MSG_LENGTH, fid ) == NULL )
01599 break;
01600 if( strstr( (char*)m_message, "END OF HEADER" ) != NULL )
01601 break;
01602 }
01603
01604
01605 while( !feof(fid) && ferror(fid)==0 )
01606 {
01607 if( fgets( (char*)m_message, GNSS_RXDATA_MSG_LENGTH, fid ) == NULL )
01608 break;
01609 line_count++;
01610 }
01611
01612 fclose(fid);
01613
01614
01615 estimated_nr_eph = line_count/8;
01616
01617 estimated_nr_eph += 32;
01618
01619
01620 m_RINEX_eph.eph_array = NULL;
01621 m_RINEX_eph.eph_array = new GPS_structEphemeris[estimated_nr_eph];
01622 if( m_RINEX_eph.eph_array == NULL )
01623 return FALSE;
01624
01625 m_RINEX_eph.max_array_length = estimated_nr_eph;
01626
01627 result = RINEX_DecodeGPSNavigationFile(
01628 m_RINEX_eph.filepath.c_str(),
01629 &m_RINEX_eph.iono_model,
01630 m_RINEX_eph.eph_array,
01631 m_RINEX_eph.max_array_length,
01632 &m_RINEX_eph.array_length
01633 );
01634 if( result == FALSE )
01635 return false;
01636
01637 return true;
01638 }
01639
01640 bool GNSS_RxData::UpdateTheEphemerisArrayWithUsingRINEX()
01641 {
01642 int RINEX_eph_index = -1;
01643 unsigned i = 0;
01644 unsigned j = 0;
01645 unsigned k = 0;
01646 unsigned short eph_week = 0;
01647 unsigned eph_tow = 0;
01648 bool result = false;
01649 double eph_time = 0;
01650 double current_eph_time = 0;
01651 const double rx_time = m_pvt.time.gps_week*SECONDS_IN_WEEK + m_pvt.time.gps_tow;
01652 bool isEphUpToDate;
01653 bool isAvailable;
01654
01655
01656
01657
01658
01659
01660
01661
01662 for( j = 0; j < m_nrValidObs; j++ )
01663 {
01664 RINEX_eph_index = -1;
01665 eph_time = 0;
01666 current_eph_time = 0;
01667 isEphUpToDate = false;
01668 isAvailable = false;
01669 if( m_ObsArray[j].flags.isActive )
01670 {
01671 if( m_ObsArray[j].system == GNSS_GPS )
01672 {
01673
01674
01675
01676 result = m_EphAlmArray.GetEphemerisTOW(
01677 m_ObsArray[j].id,
01678 isAvailable,
01679 eph_week,
01680 eph_tow
01681 );
01682 if( !result )
01683 return false;
01684
01685 if( isAvailable )
01686 {
01687 current_eph_time = eph_week*SECONDS_IN_WEEK + eph_tow;
01688 }
01689
01690
01691
01692 for( k = 0; k < m_RINEX_eph.array_length; k++ )
01693 {
01694 if( m_RINEX_eph.eph_array[k].prn == m_ObsArray[j].id )
01695 {
01696 eph_time = m_RINEX_eph.eph_array[k].tow_week*SECONDS_IN_WEEK + m_RINEX_eph.eph_array[k].tow;
01697
01698 if( !isAvailable )
01699 {
01700 if( rx_time > eph_time )
01701 {
01702 RINEX_eph_index = k;
01703 }
01704 else
01705 {
01706 if( RINEX_eph_index >= 0 )
01707 {
01708 result = m_EphAlmArray.AddEphemeris(
01709 m_RINEX_eph.eph_array[RINEX_eph_index].prn,
01710 m_RINEX_eph.eph_array[RINEX_eph_index]
01711 );
01712 if( !result )
01713 return false;
01714 isEphUpToDate = true;
01715 break;
01716 }
01717 else
01718 {
01719
01720 break;
01721 }
01722 }
01723 }
01724 else
01725 {
01726 if( rx_time > eph_time )
01727 {
01728 if( current_eph_time < eph_time )
01729 {
01730 RINEX_eph_index = k;
01731 }
01732 }
01733 else
01734 {
01735 if( RINEX_eph_index >= 0 )
01736 {
01737 result = m_EphAlmArray.AddEphemeris(
01738 m_RINEX_eph.eph_array[RINEX_eph_index].prn,
01739 m_RINEX_eph.eph_array[RINEX_eph_index]
01740 );
01741 if( !result )
01742 return false;
01743 isEphUpToDate = true;
01744 }
01745 break;
01746 }
01747 }
01748 }
01749 }
01750
01751
01752 if( !isEphUpToDate )
01753 {
01754 if( RINEX_eph_index >= 0 )
01755 {
01756 result = m_EphAlmArray.AddEphemeris(
01757 m_RINEX_eph.eph_array[RINEX_eph_index].prn,
01758 m_RINEX_eph.eph_array[RINEX_eph_index]
01759 );
01760 if( !result )
01761 return false;
01762 isEphUpToDate = true;
01763 }
01764 }
01765 }
01766 }
01767 }
01768
01769
01770 for( j = 0; j < m_nrValidObs; j++ )
01771 {
01772 if( m_ObsArray[j].flags.isActive )
01773 {
01774 if( m_ObsArray[j].system == GNSS_GPS )
01775 {
01776 result = m_EphAlmArray.IsEphemerisAvailable( m_ObsArray[j].id, isAvailable );
01777 if( !result )
01778 return false;
01779
01780 m_ObsArray[j].flags.isEphemerisValid = isAvailable;
01781 }
01782 }
01783 }
01784
01785
01786
01787 return true;
01788 }
01789
01790
01791 }
01792
01793
01794