Changeset 11042 in ntrip
- Timestamp:
- Sep 22, 2026, 5:19:12 PM (64 minutes ago)
- Location:
- trunk/BNC/src
- Files:
-
- 9 edited
-
PPP/pppSatObs.cpp (modified) (2 diffs)
-
RTCM3/clock_and_orbit/clock_orbit.h (modified) (1 diff)
-
RTCM3/clock_and_orbit/clock_orbit_igs.cpp (modified) (1 diff)
-
RTCM3/clock_and_orbit/clock_orbit_igs.h (modified) (1 diff)
-
RTCM3/clock_and_orbit/clock_orbit_rtcm.cpp (modified) (1 diff)
-
RTCM3/clock_and_orbit/clock_orbit_rtcm.h (modified) (1 diff)
-
RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp (modified) (2 diffs)
-
RTCM3/clock_and_orbit/clock_orbit_rtcm_new.h (modified) (1 diff)
-
bnchelp.html (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/src/PPP/pppSatObs.cpp
r11041 r11042 409 409 // provider is relied on to keep DF+010 synchronized with DF+069 across all 410 410 // systems for this to work. 411 //////////////////////////////////////////////////////////////////////////// 412 static bool ssrSatAntennaTrusted(const t_satAntenna* satAntenna) { 411 // 412 // Separately, providers only guarantee SatelliteAntennaIOD uniqueness within 413 // a rolling 64-day window (it wraps/repeats after that), so a client that 414 // has been without a fresh Antenna message for that system for 64 days or 415 // more must treat any cached data as unverifiable and stop using it, even 416 // if the IOD/Metadata check above would otherwise pass - the same IOD value 417 // could by then legitimately mean something else. epoTime is the current 418 // processing epoch, compared against t_satAntenna::_time (when this data 419 // was actually decoded, not a wire epoch - the message carries none). 420 //////////////////////////////////////////////////////////////////////////// 421 static bool ssrSatAntennaTrusted(const t_satAntenna* satAntenna, const bncTime& epoTime) { 422 const double MAX_AGE_SEC = 64.0 * 86400.0; 413 423 if (!satAntenna || satAntenna->_satelliteAntennaIOD == 0) { 424 return false; 425 } 426 if (epoTime.valid() && satAntenna->_time.valid() && 427 epoTime - satAntenna->_time >= MAX_AGE_SEC) { 414 428 return false; 415 429 } … … 543 557 if (PPP_CLIENT->antex()) { 544 558 const t_satAntenna* satAntenna = PPP_CLIENT->obsPool()->satAntenna(_prn); 545 if (!ssrSatAntennaTrusted(satAntenna)) { 559 if (!ssrSatAntennaTrusted(satAntenna, _time)) { 546 560 satAntenna = 0; // untrusted (IOD zero, or not confirmed via Metadata) - fall back to ANTEX 547 561 } -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit.h
r11041 r11042 604 604 #define E_NADIR_ANGLE_DEPENDENT_CORR_RANGE_EXTENSION(a) ADDBITS(4, a) /* DF+015 (new RTCM) to extend DF+021*/ 605 605 #define E_SATELLITE_SET_INDICATOR(a) ADDBITS(1, a) /* DF+016 (new RTCM) */ 606 #define E_SATELLITE_MASK(a) ADDBITS(64, a) /* DF394 */ 606 /* ADDBITS' mask "(1<<a)-1" uses a 32-bit int literal, so a plain 607 ADDBITS(64, a) is broken the same way GETSSRBITS(a, 64) was on decode 608 (see D_SATELLITE_MASK) - here even ADDBITS(32, ...) is unsafe, since 609 shifting a 32-bit int by exactly its own width is undefined behavior 610 too. Stay well clear of that edge by writing four 16-bit chunks. */ 611 #define E_SATELLITE_MASK(a) { \ 612 uint64_t mask64_ = (a); \ 613 ADDBITS(16, (mask64_ >> 48) & 0xFFFFU) \ 614 ADDBITS(16, (mask64_ >> 32) & 0xFFFFU) \ 615 ADDBITS(16, (mask64_ >> 16) & 0xFFFFU) \ 616 ADDBITS(16, mask64_ & 0xFFFFU) \ 617 } /* DF394 */ 607 618 #define E_FREQUENCY_SET_INDICATOR(a) ADDBITS(1, a) /* DF+017 (new RTCM) */ 608 619 #define E_GNSS_FREQUENCY_MASK(a) ADDBITS(6, a) /* DF+018 (new RTCM) */ -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_igs.cpp
r11041 r11042 945 945 } 946 946 947 // 948 //////////////////////////////////////////////////////////////////////////// 949 size_t SsrCorrIgs::MakeAntenna(const struct Antenna*, SatAntennaType, char*, size_t) { 950 // This format does not encode Satellite Antenna message content; nothing 951 // to encode. 952 return 0; 953 } 954 -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_igs.h
r11041 r11042 227 227 size_t MakeVTEC(const struct VTEC *v, int moremessagesfollow, char *buffer, size_t size); 228 228 size_t MakeMetaData(const struct MetaData *md, char *buffer, size_t size); 229 size_t MakeAntenna(const struct Antenna *a, SatAntennaType type, char *buffer, size_t size); 229 230 enum GCOB_RETURN GetSSR(struct ClockOrbit *co, struct CodeBias *cb, struct VTEC *v, 230 231 struct PhaseBias *pb, struct MetaData *md, struct Antenna* a, -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm.cpp
r11041 r11042 1399 1399 } 1400 1400 1401 // 1402 //////////////////////////////////////////////////////////////////////////// 1403 size_t SsrCorrRtcm::MakeAntenna(const struct Antenna*, SatAntennaType, char*, size_t) { 1404 // Satellite Antenna messages are not defined in (old) RTCM-SSR; nothing 1405 // to encode. 1406 return 0; 1407 } 1408 -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm.h
r11041 r11042 226 226 size_t MakeVTEC(const struct VTEC *v, int moremessagesfollow, char *buffer, size_t size); 227 227 size_t MakeMetaData(const struct MetaData *md, char *buffer, size_t size); 228 size_t MakeAntenna(const struct Antenna *a, SatAntennaType type, char *buffer, size_t size); 228 229 enum GCOB_RETURN GetSSR(struct ClockOrbit *co, struct CodeBias *cb, struct VTEC *v, 229 230 struct PhaseBias *pb, struct MetaData *md, struct Antenna* a, -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp
r11041 r11042 495 495 } 496 496 497 // 498 //////////////////////////////////////////////////////////////////////////// 499 size_t SsrCorrRtcmNew::MakeAntenna(const struct Antenna* a, SatAntennaType type, 500 char* buffer, size_t size) { 501 unsigned int s, k, satBlockIdx, freqBlockIdx, deg, f, numSatBlocks, numFreqBlocks; 502 unsigned int satPositions[64], numSatPositions; 503 unsigned int freqPositions[ANT_MAXFREQUENCIES], numFreqPositions; 504 505 STARTDATA 506 507 for (s = 0; s < CLOCKORBIT_SATNUM; ++s) { 508 if (a->SatelliteMask[s] == 0 || 509 !(type == SATANTTYPE_AUTO || type == corType[s][COBOFS_SATANT])) { 510 continue; 511 } 512 INITBLOCK 513 E_RTCM_MESSAGE_NUMBER(corType[s][COBOFS_SATANT]) 514 E_SSR_PROVIDER_ID(a->SSRProviderID[s]) 515 E_SATELLITE_ANTENNA_IOD(a->SatelliteAntennaIOD[s]) 516 E_PHASE_CENTER_INFO_INDICATOR(a->PhaseCenterInformationIndicator[s]) 517 E_GROUP_DELAY_INFO_INDICATOR(a->GroupDelayInformationIndicator[s]) 518 E_NADIR_ANGLE_DEPENDENT_CORR_INDICATOR(a->NadirAngleDependentCorrectionIndicator[s]) 519 if (a->NadirAngleDependentCorrectionIndicator[s]) { 520 E_MAXIMUM_OFF_NADIR_ANGLE(a->maximumOffNadirAngle[s]) 521 E_NADIR_ANGLE_DEPENDENT_CORR_RANGE_EXTENSION(a->NadirAngleDependentCorrectionRangeExtension[s]) 522 } 523 E_SATELLITE_SET_INDICATOR(a->SatelliteSetIndicator[s]) 524 E_SATELLITE_MASK(a->SatelliteMask[s]) 525 526 /* same MSB-first mask convention as D_SATELLITE_MASK/GetSSR */ 527 numSatPositions = 0; 528 for (k = 0; k < 64 && satoffset[s] + k < satoffset[s + 1]; ++k) { 529 if ((a->SatelliteMask[s] >> (63 - k)) & 1ULL) { 530 satPositions[numSatPositions++] = satoffset[s] + k; 531 } 532 } 533 numSatBlocks = a->SatelliteSetIndicator[s] ? (numSatPositions ? 1 : 0) : numSatPositions; 534 535 for (satBlockIdx = 0; satBlockIdx < numSatBlocks; ++satBlockIdx) { 536 /* satellites sharing a block (SatelliteSetIndicator set) must 537 already carry identical Sat[] content - the caller is 538 responsible for that, same as the encoder trusts NumberOfSat 539 elsewhere; only the first masked satellite's data is sent */ 540 const struct Antenna::SatellitePart& satBlock = a->Sat[satPositions[satBlockIdx]]; 541 E_FREQUENCY_SET_INDICATOR(satBlock.FrequencySetIndicator) 542 E_GNSS_FREQUENCY_MASK(satBlock.GnssFrequencyMask) 543 544 numFreqPositions = 0; 545 for (k = 0; k < ANT_MAXFREQUENCIES; ++k) { 546 if ((satBlock.GnssFrequencyMask >> (ANT_MAXFREQUENCIES - 1 - k)) & 1U) { 547 freqPositions[numFreqPositions++] = k; 548 } 549 } 550 numFreqBlocks = satBlock.FrequencySetIndicator ? (numFreqPositions ? 1 : 0) : numFreqPositions; 551 552 for (freqBlockIdx = 0; freqBlockIdx < numFreqBlocks; ++freqBlockIdx) { 553 f = satBlock.FrequencySetIndicator ? freqPositions[0] : freqPositions[freqBlockIdx]; 554 E_NADIR_CORR_INDICATOR(satBlock.Freq[f].NadirCorrectionIndicator) 555 if (satBlock.Freq[f].NadirCorrectionIndicator) { 556 E_NADIR_CORRECTION(satBlock.Freq[f].NadirCorrection) 557 } 558 if (a->NadirAngleDependentCorrectionIndicator[s]) { 559 for (deg = 0; deg <= a->maximumOffNadirAngle[s] && deg < ANT_MAXNADIRDEGREES; ++deg) { 560 E_NADIR_ANGLE_DEPENDENT_CORRECTION(satBlock.Freq[f].NadirAngleCorrection[deg], 561 a->NadirAngleDependentCorrectionRangeExtension[s]) 562 } 563 } 564 } 565 } 566 ENDBLOCK 567 } 568 return ressize; 569 } 570 497 571 enum GCOB_RETURN SsrCorrRtcmNew::GetSSR(struct ClockOrbit* co, struct CodeBias* cb, struct VTEC* v, 498 572 struct PhaseBias* pb, struct MetaData* md, struct Antenna* a, const char* buffer, size_t size, int* bytesused) { … … 1152 1226 1153 1227 for (satBlockIdx = 0; satBlockIdx < numSatBlocks; ++satBlockIdx) { 1154 struct Antenna::SatellitePart satBlock; 1228 /* zero-initialized, not just declared: DF+019/DF+013 unset means the 1229 correction IS zero (not "not present"), per spec - a plain 1230 declaration left NadirCorrection/NadirAngleCorrection as 1231 uninitialized stack garbage for every satellite/frequency whose 1232 indicator was 0, which is nearly all of them in real data. This 1233 went unnoticed because normal call depth happened to leave zero 1234 there; it surfaced via a deeper (nested) call stack during 1235 MakeAntenna round-trip testing. */ 1236 struct Antenna::SatellitePart satBlock = {}; 1155 1237 D_FREQUENCY_SET_INDICATOR(satBlock.FrequencySetIndicator) 1156 1238 D_GNSS_FREQUENCY_MASK(satBlock.GnssFrequencyMask) -
trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.h
r11041 r11042 280 280 size_t MakeVTEC(const struct VTEC *v, int moremessagesfollow, char *buffer, size_t size); 281 281 size_t MakeMetaData(const struct MetaData *md, char *buffer, size_t size); 282 size_t MakeAntenna(const struct Antenna *a, SatAntennaType type, char *buffer, size_t size); 282 283 enum GCOB_RETURN GetSSR(struct ClockOrbit *co, struct CodeBias *cb, struct VTEC *v, 283 284 struct PhaseBias *pb, struct MetaData *md, struct Antenna* a, -
trunk/BNC/src/bnchelp.html
r11027 r11042 4615 4615 <ol type="1"> 4616 4616 <li>Special character '>' is the first character in each 'Epoch Record' (as we have it in RINEX Version 3)</li> 4617 <li>SSR message or topic descriptor, valid descriptors are:<br>ORBIT, CLOCK, CODE_BIAS, PHASE_BIAS, or VTEC</li>4617 <li>SSR message or topic descriptor, valid descriptors are:<br>ORBIT, CLOCK, CODE_BIAS, PHASE_BIAS, VTEC, META_DATA, or SAT_ANTENNA</li> 4618 4618 <li>Year, GPS time</li> 4619 4619 <li>Month, GPS time</li> … … 4652 4652 <pre><p style="font-family:Monospace"> 4653 4653 > ORBIT 2022 10 01 23 59 45.0 2 110 SSRA00CNE1 4654 2 4654 4655 G01 93 -0.1588 -0.8664 -0.0600 0.2210 -0.1200 -0.0400 4655 4656 G02 33 0.0491 -1.7468 0.5608 0.1820 0.0040 0.0200 … … 4672 4673 <p></pre> 4673 4674 4675 <p> 4676 The second record in this block provides one parameter, an SSR source format indicator: 4677 <ul> 4678 <li>SSR source format indicator<br> 4679 0 − unknown<br> 4680 1 − (old) RTCM-SSR / IGS-SSR<br> 4681 2 − (new) RTCM-SSR 4682 </li> 4683 </ul> 4684 This indicator determines which relativistic correction formula applies when the orbit correction is combined 4685 with the Broadcast Ephemeris: the velocity-based formula of IS-GPS-200D 20.3.3.3.3.1 for the (new) RTCM-SSR 4686 format, or the classic eccentricity-based formula otherwise. 4687 </p> 4674 4688 Records in this block provide the following satellite specific information: 4675 4689 <ul> … … 4763 4777 <pre><p style="font-family:Monospace"> 4764 4778 > PHASE_BIAS 2022 10 01 23 59 45.0 2 110 SSRA00CNE1 4765 0 1 4779 2 0 1 4766 4780 G01 157.50000000 0.00000000 3 1C -0.6023 1 2 7 2W -0.8679 1 2 7 5I -0.8614 1 2 7 4767 4781 G02 13.35937500 0.00000000 2 1C 0.7878 1 2 4 2W 1.1236 1 2 4 … … 4783 4797 </p></pre> 4784 4798 <p> 4785 The second record in this block provides the following consistency information: 4799 The second record in this block starts with the same SSR source format indicator used in the 'ORBIT' block 4800 (0 = unknown, 1 = (old) RTCM-SSR / IGS-SSR, 2 = (new) RTCM-SSR), followed by two more numbers whose meaning 4801 depends on it, since RTCM-SSR and IGS-SSR/(old) RTCM-SSR define different phase bias parameters here: 4786 4802 <ul> 4787 4803 4788 <li>Dispersive bias consistency indicatory<br> 4789 0 − phase biases valid for non-dispersive signal only<br> 4790 1 − phase biases maintain consistency between non-dispersive and all original dispersive phase signals 4791 </li> 4792 4793 <li>MW consistency indicator<br> 4794 0 − code and phase biases are independently derived<br> 4795 1 − consistency between code and phase biases is maintained for the MW combinations 4796 </li> 4804 <li>SSR source format indicator = 2, i.e. (new) RTCM-SSR:</li> 4805 <ul> 4806 <li>Satellite Yaw Information indicator<br> 4807 0 − yaw angle/rate not provided (both fields below are zero)<br> 4808 1 − yaw angle/rate provided 4809 </li> 4810 <li>Extended Phase Bias Property ID − a satellite-specific property ID (0-15) used to correlate a 4811 later Extended Phase Bias message's wide-lane information back onto this satellite's signals</li> 4812 </ul> 4813 4814 <li>SSR source format indicator = 0 or 1, i.e. unknown or (old) RTCM-SSR/IGS-SSR:</li> 4815 <ul> 4816 <li>Dispersive Bias Consistency indicator<br> 4817 0 − phase biases valid for non-dispersive signal only<br> 4818 1 − phase biases maintain consistency between non-dispersive and all original dispersive phase 4819 signals 4820 </li> 4821 <li>MW Consistency indicator<br> 4822 0 − code and phase biases are independently derived<br> 4823 1 − consistency between code and phase biases is maintained for the MW combinations 4824 </li> 4825 </ul> 4797 4826 4798 4827 </ul> … … 4858 4887 <li>Spherical harmonic coefficients C and S, sorted by degree and order (0 to maximum)</li> 4859 4888 </ul> 4889 </p> 4890 4891 <p> 4892 <b>Example for block 'META_DATA' carrying model/correction metadata</b> 4893 </p> 4894 <pre><p style="font-family:Monospace"> 4895 > META_DATA 2026 06 26 09 00 15.0 0 3 SSRA00BKG0 4896 2 260 3 4897 3 1 0 0 0 0 4898 6 1 0 0 0 0 4899 7 1 0 0 0 0 4900 </p></pre> 4901 <p> 4902 The second record in this block provides three parameters: 4903 <ul> 4904 <li>SSR IOD</li> 4905 <li>SSR Provider ID</li> 4906 <li>SSR Solution ID</li> 4907 </ul> 4908 Following records, one per model/correction entry, provide: 4909 <ul> 4910 <li>Model/correction type indicator<br> 4911 1 − satellite antenna Phase Center Variations (PCV)<br> 4912 2 − satellite antenna Group Delay Variations (GDV)<br> 4913 3 − solid earth tides<br> 4914 4 − ocean loading<br> 4915 5 − pole tides<br> 4916 6 − relativity<br> 4917 7 − GNSS broadcast ephemeris reference 4918 </li> 4919 <li>Application indicator (whether the model/correction is applied on the provider's side)</li> 4920 <li>Non-default model indicator</li> 4921 <li>Non-default model identifier (only valid if the non-default model indicator is set)</li> 4922 <li>Data IOD indicator</li> 4923 <li>Data IOD (only valid if the Data IOD indicator is set) − for type 1 or 2, this confirms the 4924 Satellite Antenna IOD of a 'SAT_ANTENNA' block below, see there</li> 4925 </ul> 4926 </p> 4927 4928 <p> 4929 <b>Example for block 'SAT_ANTENNA' carrying satellite antenna corrections</b> 4930 </p> 4931 <pre><p style="font-family:Monospace"> 4932 > SAT_ANTENNA 2026 06 26 09 00 15.0 0 16 SSRA00BKG0 4933 G08 260 23 1 0 1 16 7 2 G1 0 0.0000 0.0000 -0.0020 -0.0030 -0.0050 -0.0060 -0.0070 -0.0090 -0.0100 -0.0100 -0.0100 -0.0100 -0.0080 -0.0060 -0.0030 0.0000 0.0060 0.0120 G2 0 0.0000 0.0000 -0.0020 -0.0030 -0.0050 -0.0060 -0.0070 -0.0090 -0.0100 -0.0100 -0.0100 -0.0100 -0.0080 -0.0060 -0.0030 0.0000 0.0060 0.0120 4934 G16 260 23 1 0 1 16 7 2 G1 0 0.0000 0.0000 0.0010 0.0030 0.0050 0.0070 0.0100 0.0110 0.0110 0.0100 0.0090 0.0070 0.0050 0.0040 0.0040 0.0050 0.0050 0.0080 G2 0 0.0000 0.0000 0.0010 0.0030 0.0050 0.0070 0.0100 0.0110 0.0110 0.0100 0.0090 0.0070 0.0050 0.0040 0.0040 0.0050 0.0050 0.0080 4935 .. 4936 </p></pre> 4937 <p> 4938 Records in this block provide the following satellite specific information: 4939 <ul> 4940 <li>GNSS Indicator and Satellite Vehicle Pseudo Random Number</li> 4941 <li>SSR Provider ID</li> 4942 <li>Satellite Antenna IOD − unique per Provider ID within a rolling 64-day period, see note below</li> 4943 <li>Phase Center Information indicator − corrections apply to phaserange observations</li> 4944 <li>Group Delay Information indicator − corrections apply to pseudorange observations</li> 4945 <li>Nadir Angle Dependent Correction indicator</li> 4946 <li>Maximum off-nadir angle [deg] (only meaningful if the previous indicator is set)</li> 4947 <li>Nadir angle dependent correction range extension (extra bit width for the correction values below)</li> 4948 <li>Number of frequencies, succeeded by frequency specific information:</li> 4949 <ul> 4950 <li>Frequency label (e.g. G1, G2, G5, R1, R2, E1, E5, E6, E7, E8, J1, J2, J5, J6, C1, C2, C5, C6, C7)</li> 4951 <li>Nadir correction indicator</li> 4952 <li>Nadir correction [m] − offset between the orbit antenna reference point and the frequency 4953 reference point along the satellite's nadir direction; zero if the indicator above is not set</li> 4954 <li>Nadir angle dependent correction [m], one value per 1-degree bin from 0 up to the maximum 4955 off-nadir angle above (only present if the Nadir Angle Dependent Correction indicator is set)</li> 4956 <li>Frequency label, ...</li> 4957 <li>etc.</li> 4958 </ul> 4959 </ul> 4960 </p> 4961 <p> 4962 Whether a given correction is a Phase Center Variation (PCV, applies to phaserange observations only), a 4963 Group Delay Variation (GDV, applies to pseudorange observations only), or both at once (same values applied to 4964 each observation type independently) is determined by the Phase Center Information and Group Delay Information 4965 indicators, not by the type of value itself. 4966 </p> 4967 <p> 4968 Before BNC's PPP client applies a satellite's antenna correction, it must be confirmed via a 'META_DATA' block: 4969 the Satellite Antenna IOD must be non-zero and must match the Data IOD of a Metadata entry of type 1 (PCV) or 4970 type 2 (GDV) − either is sufficient, since Metadata carries this IOD once globally while the Satellite 4971 Antenna IOD is GNSS-specific, so the same Metadata entries serve as the trust anchor for every GNSS. In 4972 addition, since a Satellite Antenna IOD is only guaranteed unique within a rolling 64-day period, BNC discards 4973 any Satellite Antenna correction that is 64 days or older, even if its IOD would otherwise still match, and 4974 falls back to using ANTEX-based satellite antenna corrections instead. 4860 4975 </p> 4861 4976
Note:
See TracChangeset
for help on using the changeset viewer.
