1 | // -*- C++ -*-
|
---|
2 | //
|
---|
3 | // $Id: RTCM.h,v 1.1.1.1 2006/05/30 11:05:27 mervart Exp $
|
---|
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;
|
---|
195 | op->sec = obsMapTimeTagMod3600!=3600.0 ? obsMapTimeTagMod3600 : 0.0;
|
---|
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 | } ;
|
---|