EncodeMSM7 generates an RTCM MSM7 frame for one constellation from RAWX observations. Only observations matching gnssID are included. stationID and epochMs are encoded into the MSM header. It returns ErrNoObservations if the constellation has no usable observations this epoch, or an error if gnssID
(stationID uint16, gnssID uint8, epochMs uint32, obs []RawxObservation)
| 62 | |
| 63 | // DF399 spans -8192..8191; -8192 is the unavailable marker, so 8191 is the |
| 64 | // largest magnitude it can carry. DF404 is a residual off DF399. |
| 65 | const ( |
| 66 | maxRoughRateMps = 8191 |
| 67 | invalidRoughRate = -1 << 13 // DF399 |
| 68 | invalidFineRate = -1 << 14 // DF404 |
| 69 | ) |
| 70 | |
| 71 | // GNSS signal wavelengths in meters, keyed by u-blox sigID. |
| 72 | var signalWavelength = map[uint8]map[uint8]float64{ |
| 73 | GnssGPS: {0: speedOfLight / 1575.42e6, 3: speedOfLight / 1227.60e6, 4: speedOfLight / 1227.60e6, 6: speedOfLight / 1176.45e6, 7: speedOfLight / 1176.45e6}, |
| 74 | GnssGalileo: {0: speedOfLight / 1575.42e6, 1: speedOfLight / 1575.42e6, 3: speedOfLight / 1176.45e6, 4: speedOfLight / 1176.45e6, 5: speedOfLight / 1207.14e6, 6: speedOfLight / 1207.14e6}, |
| 75 | GnssGLONASS: {0: speedOfLight / 1602.0e6, 2: speedOfLight / 1246.0e6}, |
| 76 | GnssBeiDou: {0: speedOfLight / 1561.098e6, 1: speedOfLight / 1561.098e6, 2: speedOfLight / 1207.14e6, 3: speedOfLight / 1207.14e6}, |
| 77 | } |
| 78 | |
| 79 | // MSM7 message types per constellation. |
| 80 | var msm7MsgType = map[uint8]uint16{ |
| 81 | GnssGPS: 1077, |
| 82 | GnssGLONASS: 1087, |
| 83 | GnssGalileo: 1097, |
| 84 | GnssBeiDou: 1127, |
| 85 | } |
| 86 | |
| 87 | // Signal ID to MSM signal mask bit index mapping (DF395). |
| 88 | // Bit position is 0-based from MSB (bit 0 = signal 1, bit 1 = signal 2, etc.) |
| 89 | // Values are the RTCM signal number minus one, per RTCM 10403.x tables 3.5-91 |
| 90 | // (GPS), 3.5-97 (GLONASS), 3.5-100 (Galileo), 3.5-106 (BeiDou). |
| 91 | var signalMaskBit = map[uint8]map[uint8]int{ |
| 92 | GnssGPS: {0: 1, 3: 15, 4: 14, 6: 21, 7: 22}, // 1C, 2L, 2S, 5I, 5Q |
| 93 | GnssGalileo: {0: 1, 1: 3, 3: 21, 4: 22, 5: 13, 6: 14}, // 1C, 1B, 5I, 5Q, 7I, 7Q |
| 94 | GnssGLONASS: {0: 1, 2: 7}, // 1C, 2C |
| 95 | GnssBeiDou: {0: 1, 1: 1, 2: 13, 3: 13}, // 1I, 7I; D1/D2 share a signal |
| 96 | } |
| 97 | |
| 98 | // satSig keys an observation by satellite and signal mask bit. |
| 99 | type satSig struct { |
| 100 | sv uint8 |
| 101 | bit int |
| 102 | } |
| 103 | |
| 104 | var ( |
| 105 | // droppedSats counts satellites discarded to keep a frame within the RTCM3 |
| 106 | // length field and the 64-bit cell mask. Non-zero means the caster is |
| 107 | // receiving fewer observations than the receiver tracked. |
| 108 | droppedSats atomic.Uint64 |
| 109 | |
| 110 | // nonFinitePseudoranges counts observations dropped before encoding because |
| 111 | // the receiver reported a NaN or Inf pseudorange. Unlike a ghost, which is a |
| 112 | // satellite the receiver never acquired, this is corrupt data. |
| 113 | nonFinitePseudoranges atomic.Uint64 |
| 114 | |
| 115 | voidedRoughRanges atomic.Uint64 |
| 116 | voidedRoughRates atomic.Uint64 |
| 117 | voidedFinePRs atomic.Uint64 |
| 118 | voidedFinePhases atomic.Uint64 |
| 119 | voidedFineRates atomic.Uint64 |
| 120 | receiverFlaggedPhases atomic.Uint64 |
| 121 | ) |
searching dependent graphs…