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

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

* empty log message *

File size: 25.3 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 };
505
506 if ( 24*DW.size() < start+n-1 ) {
507 cerr << "Error: Packet too short in RTCM2packet::getUnsignedBits" << endl;
508 exit(-1);
509 }
510
511 // Handle initial data word
512 // Get all data bits. Strip parity and unwanted leading bits.
513 // Store result in 24 lsb bits of tmp.
514
515 tmp = (DW[iFirst]>>6) & 0xFFFFFF;
516 tmp = ( ( tmp << start%24) & 0xFFFFFF ) >> start%24 ;
517
518 // Handle central data word
519
520 if ( iFirst<iLast ) {
521 bitField = tmp;
522 for (unsigned int iWord=iFirst+1; iWord<iLast; iWord++) {
523 tmp = (DW[iWord]>>6) & 0xFFFFFF;
524 bitField = (bitField << 24) | tmp;
525 };
526 tmp = (DW[iLast]>>6) & 0xFFFFFF;
527 };
528
529 // Handle last data word
530
531 tmp = tmp >> (23-(start+n-1)%24);
532 bitField = (bitField << ((start+n-1)%24+1)) | tmp;
533
534 // Done
535
536 return bitField;
537
538};
539
540//
541// Get signed bit field
542//
543// Bits are numbered from left (msb) to right (lsb) starting at bit 0
544//
545
546int RTCM2packet::getBits ( unsigned int start,
547 unsigned int n ) const {
548
549
550 // Checks
551
552 if (n>32) {
553 cerr << "Error: can't handle >32 bits in RTCM2packet::getBits"
554 << endl;
555 exit(-1);
556 };
557
558 if ( 24*DW.size() < start+n-1 ) {
559 cerr << "Error: Packet too short in RTCM2packet::getBits" << endl;
560 exit(-1);
561 }
562
563 return ((int)(getUnsignedBits(start,n)<<(32-n))>>(32-n));
564
565};
566
567
568//------------------------------------------------------------------------------
569//
570// RTCM2_03 (class implementation)
571//
572// Purpose:
573//
574// A class for handling RTCM 2 GPS Reference Station Parameters messages
575//
576//------------------------------------------------------------------------------
577
578void RTCM2_03::extract(const RTCM2packet& P) {
579
580 // Check validity and packet type
581
582 validMsg = (P.valid());
583 if (!validMsg) return;
584
585 validMsg = (P.ID()==03);
586 if (!validMsg) return;
587
588 // Antenna reference point coordinates
589
590 x = P.getBits( 0,32)*0.01; // X [m]
591 y = P.getBits(32,32)*0.01; // Y [m]
592 z = P.getBits(64,32)*0.01; // Z [m]
593
594};
595
596//------------------------------------------------------------------------------
597//
598// RTCM2_23 (class implementation)
599//
600// Purpose:
601//
602// A class for handling RTCM 2 Antenna Type Definition messages
603//
604//------------------------------------------------------------------------------
605
606void RTCM2_23::extract(const RTCM2packet& P) {
607
608 int nad, nas;
609
610 // Check validity and packet type
611
612 validMsg = (P.valid());
613 if (!validMsg) return;
614
615 validMsg = (P.ID()==23);
616 if (!validMsg) return;
617
618 // Antenna descriptor
619 antType = "";
620 nad = P.getUnsignedBits(3,5);
621 for (int i=0;i<nad;i++)
622 antType += (char)P.getUnsignedBits(8+i*8,8);
623
624 // Optional antenna serial numbers
625 if (P.getUnsignedBits(2,1)==1) {
626 nas = P.getUnsignedBits(19+8*nad,5);
627 antSN = "";
628 for (int i=0;i<nas;i++)
629 antSN += (char)P.getUnsignedBits(24+8*nas+i*8,8);
630 };
631
632};
633
634
635//------------------------------------------------------------------------------
636//
637// RTCM2_24 (class implementation)
638//
639// Purpose:
640//
641// A class for handling RTCM 2 Reference Station Antenna
642// Reference Point Parameter messages
643//
644//------------------------------------------------------------------------------
645
646void RTCM2_24::extract(const RTCM2packet& P) {
647
648 double dx,dy,dz;
649
650 // Check validity and packet type
651
652 validMsg = (P.valid());
653 if (!validMsg) return;
654
655 validMsg = (P.ID()==24);
656 if (!validMsg) return;
657
658 // System indicator
659
660 isGPS = (P.getUnsignedBits(118,1)==0);
661 isGLONASS = (P.getUnsignedBits(118,1)==1);
662
663 // Antenna reference point coordinates
664
665 x = 64.0*P.getBits( 0,32);
666 y = 64.0*P.getBits(40,32);
667 z = 64.0*P.getBits(80,32);
668 dx = P.getUnsignedBits( 32,6);
669 dy = P.getUnsignedBits( 72,6);
670 dz = P.getUnsignedBits(112,6);
671 x = 0.0001*( x + (x<0? -dx:+dx) );
672 y = 0.0001*( y + (y<0? -dy:+dy) );
673 z = 0.0001*( z + (z<0? -dz:+dz) );
674
675 // Antenna Height
676
677 if (P.getUnsignedBits(119,1)==1) {
678 h= P.getUnsignedBits(120,18)*0.0001;
679 };
680
681
682};
683
684
685//------------------------------------------------------------------------------
686//
687// RTCM2_Obs (class definition)
688//
689// Purpose:
690//
691// A class for handling blocks of RTCM2 18 & 19 packets that need to be
692// combined to get a complete set of measurements
693//
694// Notes:
695//
696// The class collects L1/L2 code and phase measurements for GPS and GLONASS.
697// Since the Multiple Message Indicator is inconsistently handled by various
698// receivers we simply require code and phase on L1 and L2 for a complete
699// set ob observations at a given epoch. GLONASS observations are optional,
700// but all four types (code+phase,L1+L2) must be provided, if at least one
701// is given. Also, the GLONASS message must follow the corresponding GPS
702// message.
703//
704//------------------------------------------------------------------------------
705
706// Constructor
707
708RTCM2_Obs::RTCM2_Obs() {
709
710 clear();
711
712};
713
714// Reset entire block
715
716void RTCM2_Obs::clear() {
717
718 secs=0.0; // Seconds of hour (GPS time)
719 nSat=0; // Number of space vehicles
720 PRN.resize(0); // Pseudorange [m]
721 rng_C1.resize(0); // Pseudorange [m]
722 rng_P1.resize(0); // Pseudorange [m]
723 rng_P2.resize(0); // Pseudorange [m]
724 cph_L1.resize(0); // Carrier phase [m]
725 cph_L2.resize(0); // Carrier phase [m]
726
727 availability.reset(); // Message status flags
728 pendingMsg = true; // Multiple message indicator
729
730};
731
732// Availability checks
733
734bool RTCM2_Obs::anyGPS() {
735
736 return availability.test(bit_L1rngGPS) ||
737 availability.test(bit_L2rngGPS) ||
738 availability.test(bit_L1cphGPS) ||
739 availability.test(bit_L2cphGPS);
740
741};
742
743bool RTCM2_Obs::anyGLONASS() {
744
745 return availability.test(bit_L1rngGLO) ||
746 availability.test(bit_L2rngGLO) ||
747 availability.test(bit_L1cphGLO) ||
748 availability.test(bit_L2cphGLO);
749
750};
751
752bool RTCM2_Obs::allGPS() {
753
754 return availability.test(bit_L1rngGPS) &&
755 availability.test(bit_L2rngGPS) &&
756 availability.test(bit_L1cphGPS) &&
757 availability.test(bit_L2cphGPS);
758
759};
760
761bool RTCM2_Obs::allGLONASS() {
762
763 return availability.test(bit_L1rngGLO) &&
764 availability.test(bit_L2rngGLO) &&
765 availability.test(bit_L1cphGLO) &&
766 availability.test(bit_L2cphGLO);
767
768};
769
770// Validity
771
772bool RTCM2_Obs::valid() {
773
774 return ( allGPS() && (allGLONASS() || !anyGLONASS()) && !pendingMsg );
775
776};
777
778
779//
780// Extract RTCM2 18 & 19 messages and store relevant data for future use
781//
782
783void RTCM2_Obs::extract(const RTCM2packet& P) {
784
785 bool isGPS,isCAcode,isL1,isOth;
786 int NSat,idx;
787 int sid,prn;
788 double t,rng,cph;
789
790 // Check validity and packet type
791
792 if (!P.valid()) return;
793
794 // Clear previous data if block was already complete
795
796 if (valid()) clear();
797
798 // Process carrier phase message
799
800 if ( P.ID()==18 ) {
801
802 // Number of satellites in current message
803 NSat = (P.nDataWords()-1)/2;
804
805 // Current epoch (mod 3600 sec)
806 t = 0.6*P.modZCount()
807 + P.getUnsignedBits(4,20)*1.0e-6;
808
809 // Frequency (exit if neither L1 nor L2)
810 isL1 = ( P.getUnsignedBits(0,1)==0 );
811 isOth = ( P.getUnsignedBits(1,1)==1 );
812 if (isOth) return;
813
814 // Constellation (for first satellite in message)
815 isGPS = ( P.getUnsignedBits(26,1)==0 );
816
817 // Multiple Message Indicator (only checked for first satellite)
818 pendingMsg = ( P.getUnsignedBits(24,1)==1 );
819
820 // Handle epoch: store epoch of first GPS message and
821 // check consistency of subsequent messages. GLONASS time tags
822 // are different and have to be ignored
823 if (isGPS) {
824 if ( nSat==0 ) {
825 secs = t; // Store epoch
826 }
827 else if (t!=secs) {
828 clear(); secs = t; // Clear all data, then store epoch
829 };
830 };
831
832 // Discard GLONASS obseravtions if no prior GPS observations
833 // are available
834 if (!isGPS && !anyGPS() ) return;
835
836 // Set availability flags
837
838 if ( isL1 && isGPS) availability.set(bit_L1cphGPS);
839 if (!isL1 && isGPS) availability.set(bit_L2cphGPS);
840 if ( isL1 && !isGPS) availability.set(bit_L1cphGLO);
841 if (!isL1 && !isGPS) availability.set(bit_L2cphGLO);
842
843 // Process all satellites
844
845 for (int iSat=0;iSat<NSat;iSat++){
846
847 // Code type
848 isCAcode = ( P.getUnsignedBits(iSat*48+25,1)==0 );
849
850 // Satellite
851 sid = P.getUnsignedBits(iSat*48+27,5);
852 prn = (isGPS? sid : sid+200 );
853
854 // Carrier phase measurement (mod 2^23 [cy]; sign matched to range)
855 cph = -P.getBits(iSat*48+40,32)/256.0;
856
857 // Is this a new PRN?
858 idx=-1;
859 for (unsigned int i=0;i<PRN.size();i++) {
860 if (PRN[i]==prn) { idx=i; break; };
861 };
862 if (idx==-1) {
863 // Insert new sat at end of list
864 nSat++; idx = nSat-1;
865 PRN.push_back(prn);
866 rng_C1.push_back(0.0);
867 rng_P1.push_back(0.0);
868 rng_P2.push_back(0.0);
869 cph_L1.push_back(0.0);
870 cph_L2.push_back(0.0);
871 };
872
873 // Store measurement
874 if (isL1) {
875 cph_L1[idx] = cph;
876 }
877 else {
878 cph_L2[idx] = cph;
879 };
880
881 };
882
883 };
884
885
886 // Process pseudorange message
887
888 if ( P.ID()==19 ) {
889
890 // Number of satellites in current message
891 NSat = (P.nDataWords()-1)/2;
892
893 // Current epoch (mod 3600 sec)
894 t = 0.6*P.modZCount()
895 + P.getUnsignedBits(4,20)*1.0e-6;
896
897 // Frequency (exit if neither L1 nor L2)
898 isL1 = ( P.getUnsignedBits(0,1)==0 );
899 isOth = ( P.getUnsignedBits(1,1)==1 );
900 if (isOth) return;
901
902 // Constellation (for first satellite in message)
903 isGPS = ( P.getUnsignedBits(26,1)==0 );
904
905 // Multiple Message Indicator (only checked for first satellite)
906 pendingMsg = ( P.getUnsignedBits(24,1)==1 );
907
908 // Handle epoch: store epoch of first GPS message and
909 // check consistency of subsequent messages. GLONASS time tags
910 // are different and have to be ignored
911 if (isGPS) {
912 if ( nSat==0 ) {
913 secs = t; // Store epoch
914 }
915 else if (t!=secs) {
916 clear(); secs = t; // Clear all data, then store epoch
917 };
918 };
919
920 // Discard GLONASS obseravtions if nor prior GPS observations
921 // are available
922 if (!isGPS && !anyGPS() ) return;
923
924 // Set availability flags
925 if ( isL1 && isGPS) availability.set(bit_L1rngGPS);
926 if (!isL1 && isGPS) availability.set(bit_L2rngGPS);
927 if ( isL1 && !isGPS) availability.set(bit_L1rngGLO);
928 if (!isL1 && !isGPS) availability.set(bit_L2rngGLO);
929
930 // Process all satellites
931
932 for (int iSat=0;iSat<NSat;iSat++){
933
934 // Code type
935 isCAcode = ( P.getUnsignedBits(iSat*48+25,1)==0 );
936
937 // Satellite
938 sid = P.getUnsignedBits(iSat*48+27,5);
939 prn = (isGPS? sid : sid+200 );
940
941 // Pseudorange measurement [m]
942 rng = P.getUnsignedBits(iSat*48+40,32)*0.02;
943
944 // Is this a new PRN?
945 idx=-1;
946 for (unsigned int i=0;i<PRN.size();i++) {
947 if (PRN[i]==prn) { idx=i; break; };
948 };
949 if (idx==-1) {
950 // Insert new sat at end of list
951 nSat++; idx = nSat-1;
952 PRN.push_back(prn);
953 rng_C1.push_back(0.0);
954 rng_P1.push_back(0.0);
955 rng_P2.push_back(0.0);
956 cph_L1.push_back(0.0);
957 cph_L2.push_back(0.0);
958 };
959
960 // Store measurement
961 if (isL1) {
962 if (isCAcode) rng_C1[idx] = rng;
963 rng_P1[idx] = rng;
964 }
965 else {
966 rng_P2[idx] = rng;
967 };
968
969 };
970
971 };
972
973};
974
975//
976// Resolution of 2^24 cy carrier phase ambiguity
977// caused by 32-bit data field restrictions
978//
979// Note: the RTCM standard specifies an ambiguity of +/-2^23 cy.
980// However, numerous receivers generate data in the +/-2^22 cy range.
981// A reduced ambiguity of 2^23 cy appears compatible with both cases.
982//
983
984double RTCM2_Obs::resolvedPhase_L1(int i){
985
986//const double ambig = pow(2.0,24); // as per RTCM2 spec
987 const double ambig = pow(2.0,23); // used by many receivers
988
989 double rng;
990 double n;
991
992 if (!valid() || i<0 || i>nSat-1) return 0.0;
993
994 rng = rng_C1[i];
995 if (rng==0.0) rng = rng_P1[i];
996 if (rng==0.0) return 0.0;
997
998 n = floor( (rng/lambda_L1-cph_L1[i]) / ambig + 0.5 );
999
1000 return cph_L1[i] + n*ambig;
1001
1002};
1003
1004double RTCM2_Obs::resolvedPhase_L2(int i){
1005
1006//const double ambig = pow(2.0,24); // as per RTCM2 spec
1007 const double ambig = pow(2.0,23); // used by many receivers
1008
1009 double rng;
1010 double n;
1011
1012 if (!valid() || i<0 || i>nSat-1) return 0.0;
1013
1014 rng = rng_C1[i];
1015 if (rng==0.0) rng = rng_P1[i];
1016 if (rng==0.0) return 0.0;
1017
1018 n = floor( (rng/lambda_L2-cph_L2[i]) / ambig + 0.5 );
1019
1020 return cph_L2[i] + n*ambig;
1021
1022};
1023
1024//
1025// Resolution of epoch using reference date (GPS week and secs)
1026//
1027
1028void RTCM2_Obs::resolveEpoch (int refWeek, double refSecs,
1029 int& epochWeek, double& epochSecs ) {
1030
1031 const double secsPerWeek = 604800.0;
1032
1033 epochWeek = refWeek;
1034 epochSecs = secs + 3600.0*(floor((refSecs-secs)/3600.0+0.5));
1035
1036 if (epochSecs<0 ) { epochWeek--; epochSecs+=secsPerWeek; };
1037 if (epochSecs>secsPerWeek) { epochWeek++; epochSecs-=secsPerWeek; };
1038
1039};
1040
1041}; // End of namespace rtcm2
1042
1043// ---------------- begin added by LM --------------------------------------
1044
1045#include "../bncutils.h"
1046
1047// Constructor
1048////////////////////////////////////////////////////////////////////////////
1049RTCM2::RTCM2() {
1050
1051}
1052
1053// Destructor
1054////////////////////////////////////////////////////////////////////////////
1055RTCM2::~RTCM2() {
1056
1057}
1058
1059//
1060////////////////////////////////////////////////////////////////////////////
1061void RTCM2::Decode(char* buffer, int bufLen) {
1062
1063 _buffer.append(buffer, bufLen);
1064 int refWeek;
1065 double refSecs;
1066 currentGPSWeeks(refWeek, refSecs);
1067
1068 while(true) {
1069 _PP.getPacket(_buffer);
1070 if (!_PP.valid()) {
1071 return;
1072 }
1073
1074 if ( _PP.ID()==18 || _PP.ID()==19 ) {
1075
1076 _ObsBlock.extract(_PP);
1077
1078 if (_ObsBlock.valid()) {
1079
1080 int epochWeek;
1081 double epochSecs;
1082 _ObsBlock.resolveEpoch(refWeek, refSecs, epochWeek, epochSecs);
1083
1084 for (int iSat=0; iSat < _ObsBlock.nSat; iSat++) {
1085 Observation* obs = new Observation();
1086
1087 obs->SVPRN = _ObsBlock.PRN[iSat];
1088 obs->GPSWeek = epochWeek;
1089 obs->GPSWeeks = epochSecs;
1090 obs->C1 = _ObsBlock.rng_C1[iSat];
1091 obs->P1 = _ObsBlock.rng_P1[iSat];
1092 obs->P2 = _ObsBlock.rng_P2[iSat];
1093 obs->L1 = _ObsBlock.resolvedPhase_L1(iSat);
1094 obs->L2 = _ObsBlock.resolvedPhase_L2(iSat);
1095
1096 _obsList.push_back(obs);
1097 }
1098 _ObsBlock.clear();
1099 }
1100 }
1101 }
1102}
1103
1104// ----------------- end added by LM ---------------------------------------
Note: See TracBrowser for help on using the repository browser.