source: ntrip/trunk/BNC/RTCM/RTCM2.cpp@ 241

Last change on this file since 241 was 241, checked in by mervart, 18 years ago

* empty log message *

File size: 25.4 KB
Line 
1//------------------------------------------------------------------------------
2//
3// RTCM2.cpp
4//
5// Purpose:
6//
7// Module for extraction of RTCM2 messages
8//
9// Notes:
10//
11// - The host computer is assumed to use little endian (Intel) byte order
12//
13// Last modified:
14//
15// 2006/09/17 OMO Created
16// 2006/09/19 OMO Fixed getHeader() methods
17// 2006/09/21 OMO Reduced phase ambiguity to 2^23 cycles
18//
19// (c) DLR/GSOC
20//
21//------------------------------------------------------------------------------
22
23#include <cmath>
24#include <fstream>
25#include <iomanip>
26#include <iostream>
27#include <string>
28#include <vector>
29
30#include "RTCM2.h"
31
32using namespace std;
33
34
35// GPS constants
36
37const double c_light = 299792458.0; // Speed of light [m/s]; IAU 1976
38const double f_L1 = 1575.42e6; // L1 frequency [Hz] (10.23MHz*154)
39const double f_L2 = 1227.60e6; // L2 frequency [Hz] (10.23MHz*120)
40
41const double lambda_L1 = c_light/f_L1; // L1 wavelength [m] (0.1903m)
42const double lambda_L2 = c_light/f_L2; // L2 wavelength [m]
43
44//
45// Bits for message availability checks
46//
47
48const int bit_L1rngGPS = 0;
49const int bit_L2rngGPS = 1;
50const int bit_L1cphGPS = 2;
51const int bit_L2cphGPS = 3;
52const int bit_L1rngGLO = 4;
53const int bit_L2rngGLO = 5;
54const int bit_L1cphGLO = 6;
55const int bit_L2cphGLO = 7;
56
57
58//
59// namespace rtcm2
60//
61
62namespace rtcm2 {
63
64
65//------------------------------------------------------------------------------
66//
67// class ThirtyBitWord (implementation)
68//
69// Purpose:
70//
71// Handling of RTCM2 30bit words
72//
73//------------------------------------------------------------------------------
74
75// Constructor
76
77ThirtyBitWord::ThirtyBitWord() : W(0) {
78};
79
80// Clear entire 30-bit word and 2-bit parity from previous word
81
82void ThirtyBitWord::clear() {
83 W = 0;
84};
85
86// Failure indicator for input operations
87
88bool ThirtyBitWord::fail() const {
89 return failure;
90};
91
92// Parity check
93
94bool ThirtyBitWord::validParity() const {
95
96 // Parity stuff
97
98 static const unsigned int PARITY_25 = 0xBB1F3480;
99 static const unsigned int PARITY_26 = 0x5D8F9A40;
100 static const unsigned int PARITY_27 = 0xAEC7CD00;
101 static const unsigned int PARITY_28 = 0x5763E680;
102 static const unsigned int PARITY_29 = 0x6BB1F340;
103 static const unsigned int PARITY_30 = 0x8B7A89C0;
104
105 // Look-up table for parity of eight bit bytes
106 // (parity=0 if the number of 0s and 1s is equal, else parity=1)
107 static unsigned char byteParity[] = {
108 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
109 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
110 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
111 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
112 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
113 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
114 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
115 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
116 };
117
118 // Local variables
119
120 unsigned int t, w, p;
121
122 // The sign of the data is determined by the D30* parity bit
123 // of the previous data word. If D30* is set, invert the data
124 // bits D01..D24 to obtain the d01..d24 (but leave all other
125 // bits untouched).
126
127 w = W;
128 if ( w & 0x40000000 ) w ^= 0x3FFFFFC0;
129
130 // Compute the parity of the sign corrected data bits d01..d24
131 // as described in the ICD-GPS-200
132
133 t = w & PARITY_25;
134 p = ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
135 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
136
137 t = w & PARITY_26;
138 p = (p<<1) |
139 ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
140 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
141
142 t = w & PARITY_27;
143 p = (p<<1) |
144 ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
145 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
146
147 t = w & PARITY_28;
148 p = (p<<1) |
149 ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
150 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
151
152 t = w & PARITY_29;
153 p = (p<<1) |
154 ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
155 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
156
157 t = w & PARITY_30;
158 p = (p<<1) |
159 ( byteParity[t &0xff] ^ byteParity[(t>> 8)&0xff] ^
160 byteParity[(t>>16)&0xff] ^ byteParity[(t>>24) ] );
161
162 return ( (W!=0) && ((W &0x3f) == p));
163
164};
165
166
167// Check preamble
168
169bool ThirtyBitWord::isHeader() const {
170
171 const unsigned char Preamble = 0x66;
172
173 unsigned char b = (value()>>22) & 0xFF;
174
175 return ( b==Preamble );
176
177};
178
179
180// Return entire 32-bit (current word and previous parity)
181
182unsigned int ThirtyBitWord::all() const {
183 return W;
184};
185
186
187// Return sign-corrected 30-bit (or zero if parity mismatch)
188
189unsigned int ThirtyBitWord::value() const {
190
191 unsigned int w = W;
192
193 if (validParity()) {
194 // Return data and current parity bits. Invert data bits if D30*
195 // is set and discard old parity bits.
196 if ( w & 0x40000000 ) w ^= 0x3FFFFFC0;
197 return (w & 0x3FFFFFFF);
198 }
199 else {
200 // Error; invalid parity
201 return 0;
202 };
203
204};
205
206
207
208// Append a byte with six data bits
209
210void ThirtyBitWord::append(unsigned char b) {
211
212 // Look up table for swap (left-right) of 6 data bits
213 static const unsigned char
214 swap[] = {
215 0,32,16,48, 8,40,24,56, 4,36,20,52,12,44,28,60,
216 2,34,18,50,10,42,26,58, 6,38,22,54,14,46,30,62,
217 1,33,17,49, 9,41,25,57, 5,37,21,53,13,45,29,61,
218 3,35,19,51,11,43,27,59, 7,39,23,55,15,47,31,63
219 };
220
221 // Bits 7 and 6 (of 0..7) must be "01" for valid data bytes
222 if ( (b & 0x40) != 0x40 ) {
223 failure = true;
224 return;
225 };
226
227 // Swap bits 0..5 to restore proper bit order for 30bit words
228 b = swap[ b & 0x3f];
229
230 // Fill word
231 W = ( (W <<6) | (b & 0x3f) ) ;
232
233};
234
235
236// Get next 30bit word from string
237
238void ThirtyBitWord::get(string& buf) {
239
240 // Check if string is long enough
241
242 if (buf.size()<5) {
243 failure = true;
244 return;
245 };
246
247 // Process 5 bytes and remove them from the input
248
249 for (int i=0; i<5; i++) append(buf[i]);
250 buf.erase(0,5);
251
252 failure = false;
253
254};
255
256// Get next 30bit word from file
257
258void ThirtyBitWord::get(istream& inp) {
259
260 unsigned char b;
261
262 for (int i=0; i<5; i++) {
263 inp >> b;
264 if (inp.fail()) { clear(); return; };
265 append(b);
266 };
267
268 failure = false;
269
270};
271
272// Get next header word from string
273
274void ThirtyBitWord::getHeader(string& buf) {
275
276 unsigned int W_old = W;
277 unsigned int i;
278
279 i=0;
280 while (!isHeader() || i<5 ) {
281 // Check if string is long enough; if not restore old word and exit
282 if (buf.size()-1<i) {
283 W = W_old;
284 failure = true;
285 return;
286 };
287 // Process byte
288 append(buf[i]); i++;
289 };
290
291 // Remove processed bytes from buffer
292
293 buf.erase(0,i);
294
295 failure = false;
296
297};
298
299// Get next header word from file
300
301void ThirtyBitWord::getHeader(istream& inp) {
302
303 unsigned char b;
304 unsigned int i;
305
306 i=0;
307 while ( !isHeader() || i<5 ) {
308 inp >> b;
309 if (inp.fail()) { clear(); return; };
310 append(b); i++;
311 };
312
313 failure = false;
314
315};
316
317
318//------------------------------------------------------------------------------
319//
320// RTCM2packet (class implementation)
321//
322// Purpose:
323//
324// A class for handling RTCM2 data packets
325//
326//------------------------------------------------------------------------------
327
328// Constructor
329
330RTCM2packet::RTCM2packet() {
331 clear();
332};
333
334// Initialization
335
336void RTCM2packet::clear() {
337
338 W.clear();
339
340 H1=0;
341 H2=0;
342
343 DW.resize(0,0);
344
345};
346
347// Complete packet, valid parity
348
349bool RTCM2packet::valid() const {
350
351 // The methods for creating a packet (get,">>") ensure
352 // that a packet has a consistent number of data words
353 // and a valid parity in all header and data words.
354 // Therefore a packet is either empty or valid.
355
356 return (H1!=0);
357
358};
359
360
361//
362// Gets the next packet from the buffer
363//
364
365void RTCM2packet::getPacket(std::string& buf) {
366
367 int n;
368 ThirtyBitWord W_old = W;
369 string buf_old = buf;
370
371 // Try to read a full packet. If the input buffer is too short
372 // clear all data and restore the latest 30-bit word prior to
373 // the getPacket call. The empty header word will indicate
374 // an invalid message, which signals an unsuccessful getPacket()
375 // call.
376
377 W.getHeader(buf);
378 H1 = W.value();
379 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }
380
381 W.get(buf);
382 H2 = W.value();
383 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }
384
385 n = nDataWords();
386 DW.resize(n);
387 for (int i=0; i<n; i++) {
388 W.get(buf);
389 DW[i] = W.value();
390 if (W.fail()) { clear(); W=W_old; buf=buf_old; return; }
391 };
392
393 return;
394
395};
396
397
398//
399// Gets the next packet from the input stream
400//
401
402void RTCM2packet::getPacket(std::istream& inp) {
403
404 int n;
405
406 W.getHeader(inp);
407 H1 = W.value();
408 if (W.fail()) { clear(); return; }
409
410 W.get(inp);
411 H2 = W.value();
412 if (W.fail()) { clear(); return; }
413
414 n = nDataWords();
415 DW.resize(n);
416 for (int i=0; i<n; i++) {
417 W.get(inp);
418 DW[i] = W.value();
419 if (W.fail()) { clear(); return; }
420 };
421
422 return;
423
424};
425
426//
427// Input operator
428//
429// Reads an RTCM3 packet from the input stream.
430//
431
432istream& operator >> (istream& is, RTCM2packet& p) {
433
434 p.getPacket(is);
435
436 return is;
437
438};
439
440// Access methods
441
442unsigned int RTCM2packet::header1() const {
443 return H1;
444};
445
446unsigned int RTCM2packet::header2() const {
447 return H2;
448};
449
450unsigned int RTCM2packet::dataWord(int i) const {
451 if ( (unsigned int)i < DW.size() ) {
452 return DW[i];
453 }
454 else {
455 return 0;
456 }
457};
458
459unsigned int RTCM2packet::msgType() const {
460 return ( H1>>16 & 0x003F );
461};
462
463unsigned int RTCM2packet::stationID() const {
464 return ( H1>> 6 & 0x03FF );
465};
466
467unsigned int RTCM2packet::modZCount() const {
468 return ( H2>>17 & 0x01FFF );
469};
470
471unsigned int RTCM2packet::seqNumber() const {
472 return ( H2>>14 & 0x0007 );
473};
474
475unsigned int RTCM2packet::nDataWords() const {
476 return ( H2>> 9 & 0x001F );
477};
478
479unsigned int RTCM2packet::staHealth() const {
480 return ( H2>> 6 & 0x0003 );
481};
482
483
484//
485// Get unsigned bit field
486//
487// Bits are numbered from left (msb) to right (lsb) starting at bit 0
488//
489
490unsigned int RTCM2packet::getUnsignedBits ( unsigned int start,
491 unsigned int n ) const {
492
493 unsigned int iFirst = start/24; // Index of first data word
494 unsigned int iLast = (start+n-1)/24; // Index of last data word
495 unsigned int bitField = 0;
496 unsigned int tmp;
497
498 // Checks
499
500 if (n>32) {
501 cerr << "Error: can't handle >32 bits in RTCM2packet::getUnsignedBits"
502 << endl;
503 /// exit(-1);
504 return 0;
505 };
506
507 if ( 24*DW.size() < start+n-1 ) {
508 cerr << "Error: Packet too short in RTCM2packet::getUnsignedBits" << endl;
509 //// exit(-1);
510 return 0;
511 }
512
513 // Handle initial data word
514 // Get all data bits. Strip parity and unwanted leading bits.
515 // Store result in 24 lsb bits of tmp.
516
517 tmp = (DW[iFirst]>>6) & 0xFFFFFF;
518 tmp = ( ( tmp << start%24) & 0xFFFFFF ) >> start%24 ;
519
520 // Handle central data word
521
522 if ( iFirst<iLast ) {
523 bitField = tmp;
524 for (unsigned int iWord=iFirst+1; iWord<iLast; iWord++) {
525 tmp = (DW[iWord]>>6) & 0xFFFFFF;
526 bitField = (bitField << 24) | tmp;
527 };
528 tmp = (DW[iLast]>>6) & 0xFFFFFF;
529 };
530
531 // Handle last data word
532
533 tmp = tmp >> (23-(start+n-1)%24);
534 bitField = (bitField << ((start+n-1)%24+1)) | tmp;
535
536 // Done
537
538 return bitField;
539
540};
541
542//
543// Get signed bit field
544//
545// Bits are numbered from left (msb) to right (lsb) starting at bit 0
546//
547
548int RTCM2packet::getBits ( unsigned int start,
549 unsigned int n ) const {
550
551
552 // Checks
553
554 if (n>32) {
555 cerr << "Error: can't handle >32 bits in RTCM2packet::getBits"
556 << endl;
557 //// exit(-1);
558 return 0;
559 };
560
561 if ( 24*DW.size() < start+n-1 ) {
562 cerr << "Error: Packet too short in RTCM2packet::getBits" << endl;
563 return 0;
564 }
565
566 return ((int)(getUnsignedBits(start,n)<<(32-n))>>(32-n));
567
568};
569
570
571//------------------------------------------------------------------------------
572//
573// RTCM2_03 (class implementation)
574//
575// Purpose:
576//
577// A class for handling RTCM 2 GPS Reference Station Parameters messages
578//
579//------------------------------------------------------------------------------
580
581void RTCM2_03::extract(const RTCM2packet& P) {
582
583 // Check validity and packet type
584
585 validMsg = (P.valid());
586 if (!validMsg) return;
587
588 validMsg = (P.ID()==03);
589 if (!validMsg) return;
590
591 // Antenna reference point coordinates
592
593 x = P.getBits( 0,32)*0.01; // X [m]
594 y = P.getBits(32,32)*0.01; // Y [m]
595 z = P.getBits(64,32)*0.01; // Z [m]
596
597};
598
599//------------------------------------------------------------------------------
600//
601// RTCM2_23 (class implementation)
602//
603// Purpose:
604//
605// A class for handling RTCM 2 Antenna Type Definition messages
606//
607//------------------------------------------------------------------------------
608
609void RTCM2_23::extract(const RTCM2packet& P) {
610
611 int nad, nas;
612
613 // Check validity and packet type
614
615 validMsg = (P.valid());
616 if (!validMsg) return;
617
618 validMsg = (P.ID()==23);
619 if (!validMsg) return;
620
621 // Antenna descriptor
622 antType = "";
623 nad = P.getUnsignedBits(3,5);
624 for (int i=0;i<nad;i++)
625 antType += (char)P.getUnsignedBits(8+i*8,8);
626
627 // Optional antenna serial numbers
628 if (P.getUnsignedBits(2,1)==1) {
629 nas = P.getUnsignedBits(19+8*nad,5);
630 antSN = "";
631 for (int i=0;i<nas;i++)
632 antSN += (char)P.getUnsignedBits(24+8*nas+i*8,8);
633 };
634
635};
636
637
638//------------------------------------------------------------------------------
639//
640// RTCM2_24 (class implementation)
641//
642// Purpose:
643//
644// A class for handling RTCM 2 Reference Station Antenna
645// Reference Point Parameter messages
646//
647//------------------------------------------------------------------------------
648
649void RTCM2_24::extract(const RTCM2packet& P) {
650
651 double dx,dy,dz;
652
653 // Check validity and packet type
654
655 validMsg = (P.valid());
656 if (!validMsg) return;
657
658 validMsg = (P.ID()==24);
659 if (!validMsg) return;
660
661 // System indicator
662
663 isGPS = (P.getUnsignedBits(118,1)==0);
664 isGLONASS = (P.getUnsignedBits(118,1)==1);
665
666 // Antenna reference point coordinates
667
668 x = 64.0*P.getBits( 0,32);
669 y = 64.0*P.getBits(40,32);
670 z = 64.0*P.getBits(80,32);
671 dx = P.getUnsignedBits( 32,6);
672 dy = P.getUnsignedBits( 72,6);
673 dz = P.getUnsignedBits(112,6);
674 x = 0.0001*( x + (x<0? -dx:+dx) );
675 y = 0.0001*( y + (y<0? -dy:+dy) );
676 z = 0.0001*( z + (z<0? -dz:+dz) );
677
678 // Antenna Height
679
680 if (P.getUnsignedBits(119,1)==1) {
681 h= P.getUnsignedBits(120,18)*0.0001;
682 };
683
684
685};
686
687
688//------------------------------------------------------------------------------
689//
690// RTCM2_Obs (class definition)
691//
692// Purpose:
693//
694// A class for handling blocks of RTCM2 18 & 19 packets that need to be
695// combined to get a complete set of measurements
696//
697// Notes:
698//
699// The class collects L1/L2 code and phase measurements for GPS and GLONASS.
700// Since the Multiple Message Indicator is inconsistently handled by various
701// receivers we simply require code and phase on L1 and L2 for a complete
702// set ob observations at a given epoch. GLONASS observations are optional,
703// but all four types (code+phase,L1+L2) must be provided, if at least one
704// is given. Also, the GLONASS message must follow the corresponding GPS
705// message.
706//
707//------------------------------------------------------------------------------
708
709// Constructor
710
711RTCM2_Obs::RTCM2_Obs() {
712
713 clear();
714
715};
716
717// Reset entire block
718
719void RTCM2_Obs::clear() {
720
721 secs=0.0; // Seconds of hour (GPS time)
722 nSat=0; // Number of space vehicles
723 PRN.resize(0); // Pseudorange [m]
724 rng_C1.resize(0); // Pseudorange [m]
725 rng_P1.resize(0); // Pseudorange [m]
726 rng_P2.resize(0); // Pseudorange [m]
727 cph_L1.resize(0); // Carrier phase [m]
728 cph_L2.resize(0); // Carrier phase [m]
729
730 availability.reset(); // Message status flags
731 pendingMsg = true; // Multiple message indicator
732
733};
734
735// Availability checks
736
737bool RTCM2_Obs::anyGPS() {
738
739 return availability.test(bit_L1rngGPS) ||
740 availability.test(bit_L2rngGPS) ||
741 availability.test(bit_L1cphGPS) ||
742 availability.test(bit_L2cphGPS);
743
744};
745
746bool RTCM2_Obs::anyGLONASS() {
747
748 return availability.test(bit_L1rngGLO) ||
749 availability.test(bit_L2rngGLO) ||
750 availability.test(bit_L1cphGLO) ||
751 availability.test(bit_L2cphGLO);
752
753};
754
755bool RTCM2_Obs::allGPS() {
756
757 return availability.test(bit_L1rngGPS) &&
758 availability.test(bit_L2rngGPS) &&
759 availability.test(bit_L1cphGPS) &&
760 availability.test(bit_L2cphGPS);
761
762};
763
764bool RTCM2_Obs::allGLONASS() {
765
766 return availability.test(bit_L1rngGLO) &&
767 availability.test(bit_L2rngGLO) &&
768 availability.test(bit_L1cphGLO) &&
769 availability.test(bit_L2cphGLO);
770
771};
772
773// Validity
774
775bool RTCM2_Obs::valid() {
776
777 return ( allGPS() && (allGLONASS() || !anyGLONASS()) && !pendingMsg );
778
779};
780
781
782//
783// Extract RTCM2 18 & 19 messages and store relevant data for future use
784//
785
786void RTCM2_Obs::extract(const RTCM2packet& P) {
787
788 bool isGPS,isCAcode,isL1,isOth;
789 int NSat,idx;
790 int sid,prn;
791 double t,rng,cph;
792
793 // Check validity and packet type
794
795 if (!P.valid()) return;
796
797 // Clear previous data if block was already complete
798
799 if (valid()) clear();
800
801 // Process carrier phase message
802
803 if ( P.ID()==18 ) {
804
805 // Number of satellites in current message
806 NSat = (P.nDataWords()-1)/2;
807
808 // Current epoch (mod 3600 sec)
809 t = 0.6*P.modZCount()
810 + P.getUnsignedBits(4,20)*1.0e-6;
811
812 // Frequency (exit if neither L1 nor L2)
813 isL1 = ( P.getUnsignedBits(0,1)==0 );
814 isOth = ( P.getUnsignedBits(1,1)==1 );
815 if (isOth) return;
816
817 // Constellation (for first satellite in message)
818 isGPS = ( P.getUnsignedBits(26,1)==0 );
819
820 // Multiple Message Indicator (only checked for first satellite)
821 pendingMsg = ( P.getUnsignedBits(24,1)==1 );
822
823 // Handle epoch: store epoch of first GPS message and
824 // check consistency of subsequent messages. GLONASS time tags
825 // are different and have to be ignored
826 if (isGPS) {
827 if ( nSat==0 ) {
828 secs = t; // Store epoch
829 }
830 else if (t!=secs) {
831 clear(); secs = t; // Clear all data, then store epoch
832 };
833 };
834
835 // Discard GLONASS obseravtions if no prior GPS observations
836 // are available
837 if (!isGPS && !anyGPS() ) return;
838
839 // Set availability flags
840
841 if ( isL1 && isGPS) availability.set(bit_L1cphGPS);
842 if (!isL1 && isGPS) availability.set(bit_L2cphGPS);
843 if ( isL1 && !isGPS) availability.set(bit_L1cphGLO);
844 if (!isL1 && !isGPS) availability.set(bit_L2cphGLO);
845
846 // Process all satellites
847
848 for (int iSat=0;iSat<NSat;iSat++){
849
850 // Code type
851 isCAcode = ( P.getUnsignedBits(iSat*48+25,1)==0 );
852
853 // Satellite
854 sid = P.getUnsignedBits(iSat*48+27,5);
855 prn = (isGPS? sid : sid+200 );
856
857 // Carrier phase measurement (mod 2^23 [cy]; sign matched to range)
858 cph = -P.getBits(iSat*48+40,32)/256.0;
859
860 // Is this a new PRN?
861 idx=-1;
862 for (unsigned int i=0;i<PRN.size();i++) {
863 if (PRN[i]==prn) { idx=i; break; };
864 };
865 if (idx==-1) {
866 // Insert new sat at end of list
867 nSat++; idx = nSat-1;
868 PRN.push_back(prn);
869 rng_C1.push_back(0.0);
870 rng_P1.push_back(0.0);
871 rng_P2.push_back(0.0);
872 cph_L1.push_back(0.0);
873 cph_L2.push_back(0.0);
874 };
875
876 // Store measurement
877 if (isL1) {
878 cph_L1[idx] = cph;
879 }
880 else {
881 cph_L2[idx] = cph;
882 };
883
884 };
885
886 };
887
888
889 // Process pseudorange message
890
891 if ( P.ID()==19 ) {
892
893 // Number of satellites in current message
894 NSat = (P.nDataWords()-1)/2;
895
896 // Current epoch (mod 3600 sec)
897 t = 0.6*P.modZCount()
898 + P.getUnsignedBits(4,20)*1.0e-6;
899
900 // Frequency (exit if neither L1 nor L2)
901 isL1 = ( P.getUnsignedBits(0,1)==0 );
902 isOth = ( P.getUnsignedBits(1,1)==1 );
903 if (isOth) return;
904
905 // Constellation (for first satellite in message)
906 isGPS = ( P.getUnsignedBits(26,1)==0 );
907
908 // Multiple Message Indicator (only checked for first satellite)
909 pendingMsg = ( P.getUnsignedBits(24,1)==1 );
910
911 // Handle epoch: store epoch of first GPS message and
912 // check consistency of subsequent messages. GLONASS time tags
913 // are different and have to be ignored
914 if (isGPS) {
915 if ( nSat==0 ) {
916 secs = t; // Store epoch
917 }
918 else if (t!=secs) {
919 clear(); secs = t; // Clear all data, then store epoch
920 };
921 };
922
923 // Discard GLONASS obseravtions if nor prior GPS observations
924 // are available
925 if (!isGPS && !anyGPS() ) return;
926
927 // Set availability flags
928 if ( isL1 && isGPS) availability.set(bit_L1rngGPS);
929 if (!isL1 && isGPS) availability.set(bit_L2rngGPS);
930 if ( isL1 && !isGPS) availability.set(bit_L1rngGLO);
931 if (!isL1 && !isGPS) availability.set(bit_L2rngGLO);
932
933 // Process all satellites
934
935 for (int iSat=0;iSat<NSat;iSat++){
936
937 // Code type
938 isCAcode = ( P.getUnsignedBits(iSat*48+25,1)==0 );
939
940 // Satellite
941 sid = P.getUnsignedBits(iSat*48+27,5);
942 prn = (isGPS? sid : sid+200 );
943
944 // Pseudorange measurement [m]
945 rng = P.getUnsignedBits(iSat*48+40,32)*0.02;
946
947 // Is this a new PRN?
948 idx=-1;
949 for (unsigned int i=0;i<PRN.size();i++) {
950 if (PRN[i]==prn) { idx=i; break; };
951 };
952 if (idx==-1) {
953 // Insert new sat at end of list
954 nSat++; idx = nSat-1;
955 PRN.push_back(prn);
956 rng_C1.push_back(0.0);
957 rng_P1.push_back(0.0);
958 rng_P2.push_back(0.0);
959 cph_L1.push_back(0.0);
960 cph_L2.push_back(0.0);
961 };
962
963 // Store measurement
964 if (isL1) {
965 if (isCAcode) rng_C1[idx] = rng;
966 rng_P1[idx] = rng;
967 }
968 else {
969 rng_P2[idx] = rng;
970 };
971
972 };
973
974 };
975
976};
977
978//
979// Resolution of 2^24 cy carrier phase ambiguity
980// caused by 32-bit data field restrictions
981//
982// Note: the RTCM standard specifies an ambiguity of +/-2^23 cy.
983// However, numerous receivers generate data in the +/-2^22 cy range.
984// A reduced ambiguity of 2^23 cy appears compatible with both cases.
985//
986
987double RTCM2_Obs::resolvedPhase_L1(int i){
988
989//const double ambig = pow(2.0,24); // as per RTCM2 spec
990 const double ambig = pow(2.0,23); // used by many receivers
991
992 double rng;
993 double n;
994
995 if (!valid() || i<0 || i>nSat-1) return 0.0;
996
997 rng = rng_C1[i];
998 if (rng==0.0) rng = rng_P1[i];
999 if (rng==0.0) return 0.0;
1000
1001 n = floor( (rng/lambda_L1-cph_L1[i]) / ambig + 0.5 );
1002
1003 return cph_L1[i] + n*ambig;
1004
1005};
1006
1007double RTCM2_Obs::resolvedPhase_L2(int i){
1008
1009//const double ambig = pow(2.0,24); // as per RTCM2 spec
1010 const double ambig = pow(2.0,23); // used by many receivers
1011
1012 double rng;
1013 double n;
1014
1015 if (!valid() || i<0 || i>nSat-1) return 0.0;
1016
1017 rng = rng_C1[i];
1018 if (rng==0.0) rng = rng_P1[i];
1019 if (rng==0.0) return 0.0;
1020
1021 n = floor( (rng/lambda_L2-cph_L2[i]) / ambig + 0.5 );
1022
1023 return cph_L2[i] + n*ambig;
1024
1025};
1026
1027//
1028// Resolution of epoch using reference date (GPS week and secs)
1029//
1030
1031void RTCM2_Obs::resolveEpoch (int refWeek, double refSecs,
1032 int& epochWeek, double& epochSecs ) {
1033
1034 const double secsPerWeek = 604800.0;
1035
1036 epochWeek = refWeek;
1037 epochSecs = secs + 3600.0*(floor((refSecs-secs)/3600.0+0.5));
1038
1039 if (epochSecs<0 ) { epochWeek--; epochSecs+=secsPerWeek; };
1040 if (epochSecs>secsPerWeek) { epochWeek++; epochSecs-=secsPerWeek; };
1041
1042};
1043
1044}; // End of namespace rtcm2
1045
1046// ---------------- begin added by LM --------------------------------------
1047
1048#include "../bncutils.h"
1049
1050// Constructor
1051////////////////////////////////////////////////////////////////////////////
1052RTCM2::RTCM2() {
1053
1054}
1055
1056// Destructor
1057////////////////////////////////////////////////////////////////////////////
1058RTCM2::~RTCM2() {
1059
1060}
1061
1062//
1063////////////////////////////////////////////////////////////////////////////
1064void RTCM2::Decode(char* buffer, int bufLen) {
1065
1066 _buffer.append(buffer, bufLen);
1067 int refWeek;
1068 double refSecs;
1069 currentGPSWeeks(refWeek, refSecs);
1070
1071 while(true) {
1072 _PP.getPacket(_buffer);
1073 if (!_PP.valid()) {
1074 return;
1075 }
1076
1077 if ( _PP.ID()==18 || _PP.ID()==19 ) {
1078
1079 _ObsBlock.extract(_PP);
1080
1081 if (_ObsBlock.valid()) {
1082
1083 int epochWeek;
1084 double epochSecs;
1085 _ObsBlock.resolveEpoch(refWeek, refSecs, epochWeek, epochSecs);
1086
1087 for (int iSat=0; iSat < _ObsBlock.nSat; iSat++) {
1088 //// if (_ObsBlock.PRN[iSat] > 32) continue; // Glonass not (yet) wanted
1089 Observation* obs = new Observation();
1090
1091 obs->SVPRN = _ObsBlock.PRN[iSat];
1092 obs->GPSWeek = epochWeek;
1093 obs->GPSWeeks = epochSecs;
1094 obs->C1 = _ObsBlock.rng_C1[iSat];
1095 obs->P1 = _ObsBlock.rng_P1[iSat];
1096 obs->P2 = _ObsBlock.rng_P2[iSat];
1097 obs->L1 = _ObsBlock.resolvedPhase_L1(iSat);
1098 obs->L2 = _ObsBlock.resolvedPhase_L2(iSat);
1099
1100 _obsList.push_back(obs);
1101 }
1102 _ObsBlock.clear();
1103 }
1104 }
1105 }
1106}
1107
1108// ----------------- end added by LM ---------------------------------------
Note: See TracBrowser for help on using the repository browser.