[35] | 1 | // -*- C++ -*-
|
---|
| 2 | //
|
---|
[36] | 3 | // $Id: RTCM.h,v 1.1.1.1 2006/05/30 11:05:27 mervart Exp $
|
---|
[35] | 4 |
|
---|
| 5 | #if defined(__GNUC__)
|
---|
| 6 | using namespace std;
|
---|
| 7 | #endif
|
---|
| 8 |
|
---|
| 9 | #include "GPSDecoder.h"
|
---|
| 10 | #include "m_date.h"
|
---|
| 11 | #include <cmath>
|
---|
| 12 | #include <map>
|
---|
| 13 | #include <iostream>
|
---|
| 14 | #include <sys/types.h>
|
---|
| 15 |
|
---|
| 16 | class RTCM : public GPSDecoder {
|
---|
| 17 | public:
|
---|
| 18 | RTCM(char _StationID,bool fullRange)
|
---|
| 19 | :GPSDecoder()
|
---|
| 20 | ,StationID(_StationID)
|
---|
| 21 | ,lowerBound(fullRange ? -715827883 : 715827882 )
|
---|
| 22 | ,upperBound(fullRange ? 715827882 : 1431655764 )
|
---|
| 23 | ,rolloverIntervall(fullRange ? 4294967296. /* pow(2,32) */
|
---|
| 24 | : 2147483648. /* pow(2,31) */)
|
---|
| 25 | ,debug(0)
|
---|
| 26 | ,this_word(0)
|
---|
| 27 | ,data_word(0)
|
---|
| 28 | ,next_bits(0)
|
---|
| 29 | ,rtcm_state(/* NO_SYNC */ 0)
|
---|
| 30 | ,fail_count(0)
|
---|
| 31 | ,p_fail(0)
|
---|
| 32 | ,preamble_flag(0)
|
---|
| 33 | ,sync_bit(0)
|
---|
| 34 | ,fill_shift(0)
|
---|
| 35 | ,word_sync(0)
|
---|
| 36 | ,frame_sync(0)
|
---|
| 37 | ,frame_fill(0)
|
---|
| 38 | ,word_count(0)
|
---|
| 39 | ,frame_count(0)
|
---|
| 40 | ,pf_count(0)
|
---|
| 41 | ,msg_type(0)
|
---|
| 42 | ,station_id(0)
|
---|
| 43 | ,z_count(0)
|
---|
| 44 | ,seqno(0)
|
---|
| 45 | ,msg_len(0)
|
---|
| 46 | ,health(0)
|
---|
| 47 | ,fillptr(message)
|
---|
| 48 | ,pfptr(NULL) {}
|
---|
| 49 |
|
---|
| 50 | // defined as required by baseclass
|
---|
| 51 | void Decode(char* _ptrBuffer=NULL, int _nBufLen=0) {
|
---|
| 52 | while(_nBufLen--) {
|
---|
| 53 | new_byte((u_char)*_ptrBuffer);
|
---|
| 54 | _ptrBuffer++;
|
---|
| 55 | }
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | protected:
|
---|
| 59 | // Station ID used in m_lObsList
|
---|
| 60 | char StationID;
|
---|
| 61 |
|
---|
| 62 | typedef u_int SVPRN;
|
---|
| 63 |
|
---|
| 64 | struct Rollover {
|
---|
| 65 | Rollover():lastValue(0),rollOver(0) {}
|
---|
| 66 | int lastValue;
|
---|
| 67 | int rollOver;
|
---|
| 68 | } ;
|
---|
| 69 |
|
---|
| 70 | struct RolloverChannel {
|
---|
| 71 | Rollover l1;
|
---|
| 72 | Rollover l2;
|
---|
| 73 | } ;
|
---|
| 74 |
|
---|
| 75 | typedef map<SVPRN,RolloverChannel> RolloverMap;
|
---|
| 76 | RolloverMap rolloverMap;
|
---|
| 77 |
|
---|
| 78 | // Collector for Measurement
|
---|
| 79 | struct ObsSort {
|
---|
| 80 | ObsSort():C1(0.),P2(0.),l1(0),l2(0),assigned(0) {}
|
---|
| 81 | void set_C1(double _C1) { assigned|=1; C1= _C1; }
|
---|
| 82 | void set_P2(double _P2) { assigned|=2; P2= _P2; }
|
---|
| 83 | void set_l1(int _l1) { assigned|=4; l1= _l1; }
|
---|
| 84 | void set_l2(int _l2) { assigned|=8; l2= _l2; }
|
---|
| 85 | void set_pCodeIndicator(int _pCodeIndicator){ assigned|=16; pCodeIndicator = _pCodeIndicator;}
|
---|
| 86 | void set_cumuLossOfCont(u_char _cumuLossOfCont){ assigned|=32; cumuLossOfCont = _cumuLossOfCont;}
|
---|
| 87 | bool allAssigned() const { return assigned == 63; }
|
---|
| 88 | double C1; // m
|
---|
| 89 | double P2; // m
|
---|
| 90 | int l1; // [1/256 Cycles mod int/half int ]
|
---|
| 91 | int l2; // [1/256 Cycles mod int/half int ]
|
---|
| 92 | int pCodeIndicator;
|
---|
| 93 | u_int cumuLossOfCont;
|
---|
| 94 | u_int assigned;
|
---|
| 95 | } ;
|
---|
| 96 |
|
---|
| 97 | typedef map<SVPRN,ObsSort> ObsMap;
|
---|
| 98 | ObsMap obsMap;
|
---|
| 99 |
|
---|
| 100 | // GPStime mod 3600 of current epoch
|
---|
| 101 | // GLONASS measurements/epochs are ignored
|
---|
| 102 | double obsMapTimeTagMod3600;
|
---|
| 103 |
|
---|
| 104 | // Complete mod 3600s time with the help of system time
|
---|
| 105 | // to timetag. Assume that the diffence is below 20min.
|
---|
| 106 | static long completeMod3600BySysTime(int mod3600time) {
|
---|
| 107 | const long sysTimeTag= Date::timeNow().tag_get();
|
---|
| 108 | const long offset = ((sysTimeTag%3600) < 1200) && (mod3600time > 2400)
|
---|
| 109 | ? -1
|
---|
| 110 | : ((sysTimeTag%3600) > 2400) && (mod3600time < 1200)
|
---|
| 111 | ? 1
|
---|
| 112 | : 0;
|
---|
| 113 | return ((sysTimeTag/3600)+offset)*3600 + mod3600time;
|
---|
| 114 | }
|
---|
| 115 |
|
---|
| 116 |
|
---|
| 117 | //
|
---|
| 118 | //
|
---|
| 119 | //
|
---|
| 120 | virtual void endOfEpoch(Date d) {}
|
---|
| 121 |
|
---|
| 122 | //
|
---|
| 123 | //
|
---|
| 124 | // called if reference position arises in datastream
|
---|
| 125 | virtual void onPosition(double x,double y,double z) {}
|
---|
| 126 |
|
---|
| 127 | // Rollover managment
|
---|
| 128 | int lowerBound;
|
---|
| 129 | int upperBound;
|
---|
| 130 | double rolloverIntervall;
|
---|
| 131 |
|
---|
| 132 | int rollOverCondition(int oldv,int newv) {
|
---|
| 133 | return (oldv < lowerBound && newv > upperBound )
|
---|
| 134 | ? -1
|
---|
| 135 | : (newv < lowerBound && oldv > upperBound )
|
---|
| 136 | ? 1
|
---|
| 137 | : 0;
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | //
|
---|
| 141 | //
|
---|
| 142 | //
|
---|
| 143 | void updateRollovers() {
|
---|
| 144 | ObsMap::iterator i;
|
---|
| 145 | for(i= obsMap.begin();i != obsMap.end();i++) {
|
---|
| 146 | RolloverMap::iterator rm(rolloverMap.find(i->first));
|
---|
| 147 | if(rm != rolloverMap.end()) {
|
---|
| 148 | rm->second.l1.rollOver +=
|
---|
| 149 | rollOverCondition( rm->second.l1.lastValue
|
---|
| 150 | ,i->second.l1 );
|
---|
| 151 | rm->second.l2.rollOver +=
|
---|
| 152 | rollOverCondition( rm->second.l2.lastValue
|
---|
| 153 | ,i->second.l2 );
|
---|
| 154 | } else {
|
---|
| 155 | rolloverMap[i->first].l1.rollOver= 0;
|
---|
| 156 | rolloverMap[i->first].l2.rollOver= 0;
|
---|
| 157 | }
|
---|
| 158 | rolloverMap[i->first].l1.lastValue= i->second.l1;
|
---|
| 159 | rolloverMap[i->first].l2.lastValue= i->second.l2;
|
---|
| 160 | }
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | //
|
---|
| 164 | //
|
---|
| 165 | //
|
---|
| 166 | virtual void debugOut( SVPRN svprn,long timetag,double mod3600,long mod3600int
|
---|
| 167 | ,double C1,int l1,int roll_l1,double unrolled_l1
|
---|
| 168 | ,int l2,int roll_l2,double unrolled_l2) {}
|
---|
| 169 |
|
---|
| 170 | //
|
---|
| 171 | //
|
---|
| 172 | //
|
---|
| 173 | void dumpObsMap() {
|
---|
| 174 | const int obsMapTimeTagMod3600int=int(rint(obsMapTimeTagMod3600));
|
---|
| 175 | const long timeTag = completeMod3600BySysTime(obsMapTimeTagMod3600int);
|
---|
| 176 | Date d;
|
---|
| 177 | d.tag_set(timeTag);
|
---|
| 178 |
|
---|
| 179 | updateRollovers();
|
---|
| 180 |
|
---|
| 181 | endOfEpoch(d);
|
---|
| 182 |
|
---|
| 183 | ObsMap::iterator i;
|
---|
| 184 | for(i= obsMap.begin();i != obsMap.end();i++) {
|
---|
| 185 | if(!i->second.allAssigned() ) {
|
---|
| 186 | // cerr << "incomplete measurements" << endl;
|
---|
| 187 | } else {
|
---|
| 188 | Observation *op = new Observation;
|
---|
| 189 |
|
---|
| 190 | op->StatID[0] = StationID;
|
---|
| 191 | op->StatID[1] = '\0';
|
---|
| 192 | op->SVPRN= i->first;
|
---|
| 193 | op->GPSWeek= timeTag / Date::SECONDS_PER_WEEK;
|
---|
| 194 | op->GPSWeeks= timeTag % Date::SECONDS_PER_WEEK;
|
---|
[36] | 195 | op->sec = obsMapTimeTagMod3600!=3600.0 ? obsMapTimeTagMod3600 : 0.0;
|
---|
[35] | 196 | op->C1= i->second.C1;
|
---|
| 197 | op->P2= i->second.P2;
|
---|
| 198 | op->pCodeIndicator = i->second.pCodeIndicator;
|
---|
| 199 | op->cumuLossOfCont = i->second.cumuLossOfCont;
|
---|
| 200 | const double l1_offset( rolloverMap[i->first].l1.rollOver
|
---|
| 201 | * rolloverIntervall );
|
---|
| 202 | const double unrolled_l1 = i->second.l1 + l1_offset;
|
---|
| 203 | op->L1=(unrolled_l1 / -256.) * lambda1;
|
---|
| 204 |
|
---|
| 205 | const double l2_offset( rolloverMap[i->first].l2.rollOver
|
---|
| 206 | * rolloverIntervall );
|
---|
| 207 | const double unrolled_l2 = i->second.l2 + l2_offset;
|
---|
| 208 | op->L2=(unrolled_l2 / -256.) * lambda2;
|
---|
| 209 |
|
---|
| 210 | op->SNR1= 0;
|
---|
| 211 | op->SNR2= 0;
|
---|
| 212 | m_lObsList.push_back(op);
|
---|
| 213 | debugOut( i->first,timeTag,obsMapTimeTagMod3600,obsMapTimeTagMod3600int
|
---|
| 214 | ,op->C1
|
---|
| 215 | ,i->second.l1,rolloverMap[i->first].l1.rollOver,unrolled_l1
|
---|
| 216 | ,i->second.l2,rolloverMap[i->first].l2.rollOver,unrolled_l2);
|
---|
| 217 | }
|
---|
| 218 | }
|
---|
| 219 | obsMap.clear();
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | // SC-104 V2.3 4-42 Note 1 4.
|
---|
| 223 | // Recover TimeTag ( modulo 3600s ) GPS/GLONASS Time and ClockError
|
---|
| 224 | // from expandedTimeOfMeasurement
|
---|
| 225 | // Assume receiver measurements at hard edges at a grid of 10ms
|
---|
| 226 | // and clock error as less 5 ms (1.1ms max recommended).
|
---|
| 227 | //
|
---|
| 228 | struct RecoveredTimeTagAndClockError {
|
---|
| 229 | static double fastestUpdatePeriod() { return 0.01; }
|
---|
| 230 | static double shift() { return fastestUpdatePeriod() / 2.; }
|
---|
| 231 | RecoveredTimeTagAndClockError(double expandedTimeOfMeasurement /* [s] */)
|
---|
| 232 | :clockError(fmod(expandedTimeOfMeasurement+shift(),fastestUpdatePeriod()) - shift())
|
---|
| 233 | ,timeTagMod3600(expandedTimeOfMeasurement - clockError) {}
|
---|
| 234 | double clockError; /* [s] */
|
---|
| 235 | double timeTagMod3600; /* [s] */
|
---|
| 236 | } ;
|
---|
| 237 |
|
---|
| 238 | virtual void debugTime(double timeTagMod3600,double clockError) {}
|
---|
| 239 |
|
---|
| 240 | void dumpOnNewTimeTag(double expandedTimeOfMeasurement) {
|
---|
| 241 | const RecoveredTimeTagAndClockError r(expandedTimeOfMeasurement);
|
---|
| 242 | if(r.timeTagMod3600 != obsMapTimeTagMod3600) {
|
---|
| 243 | debugTime(r.timeTagMod3600,r.clockError);
|
---|
| 244 | if(obsMap.size()) dumpObsMap();
|
---|
| 245 | obsMapTimeTagMod3600= r.timeTagMod3600;
|
---|
| 246 | }
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | int preamble();
|
---|
| 250 | void state_change(u_int s);
|
---|
| 251 | u_int parity_ok();
|
---|
| 252 | int find_sync(u_char b);
|
---|
| 253 | void next_word();
|
---|
| 254 | int filled_word(u_char b);
|
---|
| 255 |
|
---|
| 256 | void msgRTKUncorrectedCarrierPhases();
|
---|
| 257 | void msgRTKUncorrectedPseudoranges();
|
---|
| 258 |
|
---|
| 259 | void printcor();
|
---|
| 260 | void printref();
|
---|
| 261 | void printba();
|
---|
| 262 | void printspec();
|
---|
| 263 | void printnull();
|
---|
| 264 | void printdatum();
|
---|
| 265 | void printconh();
|
---|
| 266 |
|
---|
| 267 | void new_frame();
|
---|
| 268 | void buffer(u_int w);
|
---|
| 269 | void frame_start();
|
---|
| 270 | void find_start();
|
---|
| 271 | void fill_frame();
|
---|
| 272 | void status_byte(u_char b);
|
---|
| 273 | void data_byte(u_char b);
|
---|
| 274 | void new_byte(u_char b);
|
---|
| 275 |
|
---|
| 276 | int debug;
|
---|
| 277 |
|
---|
| 278 | u_int this_word, data_word;
|
---|
| 279 | u_char next_bits;
|
---|
| 280 |
|
---|
| 281 | int rtcm_state, fail_count, p_fail, preamble_flag;
|
---|
| 282 | int sync_bit, fill_shift, word_sync, frame_sync, frame_fill;
|
---|
| 283 | int word_count, frame_count, pf_count;
|
---|
| 284 | int msg_type, station_id, z_count, seqno, msg_len, health;
|
---|
| 285 |
|
---|
| 286 | u_int message[40]; /* message buffer */
|
---|
| 287 | u_int *fillptr; /* pointer to fill message */
|
---|
| 288 | u_int *pfptr; /* pointer to first parity error */
|
---|
| 289 |
|
---|
| 290 | static char *state_name[];
|
---|
| 291 | static u_int tx_speed[];
|
---|
| 292 | static u_char parity_of[];
|
---|
| 293 | static u_char reverse_bits[];
|
---|
| 294 | } ;
|
---|