319 lines
9.8 KiB
C++
319 lines
9.8 KiB
C++
#include "rtcm.hh"
|
||
#include "bits.hh"
|
||
#include <iostream>
|
||
#include <string.h>
|
||
using namespace std;
|
||
|
||
void RTCMMessage::parse(const std::string& str)
|
||
{
|
||
d_gm={};
|
||
// memset(&d_gm, 0, sizeof(d_gm));
|
||
auto gbu=[&str](int offset, int bits) {
|
||
return getbitu((const unsigned char*)str.c_str(), offset, bits);
|
||
};
|
||
auto gbum=[&str](int& offset, int bits) {
|
||
unsigned int ret = getbitu((const unsigned char*)str.c_str(), offset, bits);
|
||
offset += bits;
|
||
return ret;
|
||
};
|
||
|
||
auto gbs=[&str](int offset, int bits) {
|
||
return getbits((const unsigned char*)str.c_str(), offset, bits);
|
||
};
|
||
|
||
auto gbsm=[&str](int& offset, int bits) {
|
||
int ret = getbits((const unsigned char*)str.c_str(), offset, bits);
|
||
offset += bits;
|
||
return ret;
|
||
};
|
||
|
||
|
||
type = gbu(0, 12);
|
||
// cout<<"Message number: "<<type << " of size "<<str.size()<<"\n";
|
||
if(type == 1057 || type == 1240) {
|
||
d_ephs.clear();
|
||
int stride;
|
||
int iodlen;
|
||
if(type == 1057) { // GPS
|
||
stride = 135;
|
||
iodlen=8;
|
||
}
|
||
else { // Galileo
|
||
stride=137;
|
||
iodlen=10;
|
||
}
|
||
|
||
int sats = gbu(62, 6);
|
||
sow = gbu(12, 20); // this is DF385
|
||
udi = gbu(32, 4);
|
||
mmi = gbu(36, 1);
|
||
reference = gbu(37,1);
|
||
ssrIOD = gbu(38,4);
|
||
ssrProvider = gbu(42, 16);
|
||
ssrSolution = gbu(58, 4);
|
||
|
||
// cout <<" sow "<< sow <<" sats "<<sats<<" update interval " << udi <<" mmi " << mmi;
|
||
// cout <<" reference "<< reference << " iod-ssr "<< ssrIOD << " ssr-provider " << ssrProvider << " ssr-solution ";
|
||
// cout<< ssrSolution <<":\n";
|
||
|
||
for(int n = 0; n < sats; ++n) {
|
||
EphemerisDelta ed;
|
||
|
||
int off = 68+stride*n;
|
||
ed.radial = gbs(off+ iodlen + 6, 22) * 0.1; // we store this in millimeters
|
||
ed.along = gbs(off+ iodlen+ 28, 20) * 0.4;
|
||
ed.cross = gbs(off+ iodlen+48, 20) * 0.4;
|
||
|
||
ed.dradial = gbs(off + iodlen+ 68, 21) * 0.001; // we store this in mm/s
|
||
ed.dalong = gbs(off + iodlen + 89, 19) * 0.004;
|
||
ed.dcross = gbs(off + iodlen +108, 19) * 0.004;
|
||
ed.iod = gbu(off +6, iodlen);
|
||
ed.sow = sow;
|
||
ed.udi = udi;
|
||
if(type == 1057) {
|
||
ed.id.gnss = 0;
|
||
ed.id.sigid = 0;
|
||
}
|
||
else if(type == 1240) {
|
||
ed.id.gnss = 2;
|
||
ed.id.sigid = 1;
|
||
}
|
||
|
||
ed.id.sv = gbu(off + 0, 6);
|
||
// cout<<" "<<makeSatIDName(ed.id)<<" iode "<< ed.iod<<" ("<< ed.radial<<", "<<ed.along<<", "<<ed.cross<<") mm -> (";
|
||
// cout<< ed.dradial<<", "<<ed.dalong<<", "<<ed.dcross<< ") mm/s\n";
|
||
d_ephs.push_back(ed);
|
||
}
|
||
}
|
||
else if(type == 1058 || type == 1241) {
|
||
d_clocks.clear();
|
||
int sats = gbu(61, 6);
|
||
sow = gbu(12, 20);
|
||
udi = gbu(32, 4);
|
||
mmi = gbu(36, 1);
|
||
ssrIOD = gbu(37, 4);
|
||
ssrProvider = gbu(41, 16);
|
||
ssrSolution=gbu(57, 4);
|
||
|
||
// cout <<" sow "<< sow <<" sats "<<sats<<" update interval " << udi <<" mmi " << mmi;
|
||
// cout << " iod-ssr "<< ssrIOD << " ssr-provider " << ssrProvider << " ssr-solution ";
|
||
// cout<< ssrSolution <<":\n";
|
||
|
||
for(int n = 0; n < sats; ++n) {
|
||
ClockDelta cd;
|
||
cd.sow = sow;
|
||
cd.udi = udi;
|
||
if(type == 1058) {
|
||
cd.id.gnss = 0;
|
||
cd.id.sigid = 0;
|
||
}
|
||
else if(type == 1241) {
|
||
cd.id.gnss = 2;
|
||
cd.id.sigid = 1;
|
||
}
|
||
|
||
int off = 67+76*n;
|
||
cd.id.sv = gbu(off +0, 6);
|
||
|
||
/*
|
||
C0 polynomial coefficient for correction of broadcast satellite clock.
|
||
The reference time t0 is Epoch Time (DF385, DF386) plus 1⁄2 SSR
|
||
Update Interval. The reference time t0 for SSR Update Interval “0” is
|
||
Epoch Time
|
||
|
||
DF 385: Full seconds since the beginning of the GPS week
|
||
|
||
*/
|
||
|
||
cd.dclock0 = gbs(off + 6, 22)*1e-4; // in 0.1 mm, this converts to meters
|
||
cd.dclock1 = gbs(off + 28, 21)*1e-6; // meter/s
|
||
cd.dclock2 = gbs(off + 49, 27)*2e-8; // meter/s^2
|
||
d_clocks.push_back(cd);
|
||
// cout<<" "<< makeSatIDName(cd.id)<<" ";
|
||
// cout<< cd.dclock0 <<" ";
|
||
// cout<< cd.dclock1 <<" ";
|
||
// cout<< cd.dclock2 << endl;
|
||
}
|
||
}
|
||
else if(type == 1060 || type == 1243) { // combined
|
||
int sow = gbu(12, 20);
|
||
int udi = gbu(32, 4);
|
||
// int mmi = gbu(36, 1);
|
||
// int srd = gbu(37, 1);
|
||
ssrIOD = gbu(38, 4);
|
||
ssrProvider = gbu(42, 16);
|
||
ssrSolution=gbu(58, 4);
|
||
unsigned int numsats=gbu(62, 6);
|
||
|
||
int offset=68;
|
||
d_ephs.clear();
|
||
d_clocks.clear();
|
||
int iodlen = type == 1060 ? 8 : 10;
|
||
for(unsigned int n=0; n < numsats; ++n) {
|
||
ClockDelta cd;
|
||
EphemerisDelta ed;
|
||
|
||
int off = offset + n*(197 + iodlen);
|
||
cd.sow = ed.sow = sow;
|
||
cd.udi = ed.udi = udi;
|
||
cd.id.gnss = (type == 1060) ? 0 : 2; // GPS or Galileo
|
||
cd.id.sv = gbu(off + 0, 6);
|
||
cd.id.sigid = (type == 1060) ? 0 : 1;
|
||
|
||
ed.id = cd.id;
|
||
ed.iod = gbu(off + 6, iodlen);
|
||
int shift = iodlen - 8;
|
||
ed.radial = gbs(off + 14 + shift, 22 ) * 0.1; // we store this in millimeters
|
||
ed.along = gbs(off + 36 + shift, 20 ) * 0.4;
|
||
ed.cross = gbs(off + 56 + shift, 20 ) * 0.4;
|
||
|
||
ed.dradial= gbs(off + 76 + shift, 21) * 0.001; // we store this in mm/s
|
||
ed.dalong = gbs(off + 97 + shift, 19) * 0.004;
|
||
ed.dcross = gbs(off +116 + shift, 19) * 0.004;
|
||
|
||
d_ephs.push_back(ed);
|
||
cd.iod = ed.iod;
|
||
cd.dclock0 = gbs(off + 135 + shift, 22)*1e-4; // in 0.1 mm, this converts to meters
|
||
cd.dclock1 = gbs(off + 157 + shift, 21)*1e-6; // meter/s
|
||
cd.dclock2 = gbs(off + 178 + shift, 27)*2e-8; // meter/s^2
|
||
// 205 / 207
|
||
d_clocks.push_back(cd);
|
||
}
|
||
}
|
||
else if(type == 1045 || type == 1046) { // F/NAV or I/NAV respectively ephemeris
|
||
int off=12;
|
||
d_sv = gbum(off, 6);
|
||
d_gm.wn = gbum(off, 12);
|
||
d_gm.iodnav = gbum(off, 10);
|
||
d_gm.sisa = gbum(off, 8);
|
||
d_gm.idot = gbsm(off, 14);
|
||
d_gm.t0c = gbum(off, 14);
|
||
d_gm.af2 = gbsm(off, 6);
|
||
d_gm.af1 = gbsm(off, 21);
|
||
d_gm.af0 = gbsm(off, 31);
|
||
//
|
||
d_gm.crs = gbsm(off, 16);
|
||
d_gm.deltan = gbsm(off, 16);
|
||
d_gm.m0 = gbsm(off, 32);
|
||
d_gm.cuc = gbsm(off, 16);
|
||
d_gm.e = gbum(off, 32);
|
||
d_gm.cus = gbsm(off, 16);
|
||
d_gm.sqrtA = gbum(off, 32);
|
||
d_gm.t0e = gbum(off, 14);
|
||
//
|
||
|
||
d_gm.cic = gbsm(off, 16);
|
||
d_gm.omega0 = gbsm(off, 32);
|
||
d_gm.cis = gbsm(off, 16);
|
||
d_gm.i0 = gbsm(off, 32);
|
||
d_gm.crc = gbsm(off, 16);
|
||
d_gm.omega = gbsm(off, 32);
|
||
d_gm.omegadot = gbsm(off, 24);
|
||
|
||
// 16 + 16 + 32 + 16 + 32 + 16 + 32 + 14 +
|
||
// crs deln M0 cuc e cus sqrA toe cic OM0 cis i0 crc omeg omegdot
|
||
// off += 16+ 32 +16 + 32 + 16 + 32 +24;
|
||
d_gm.BGDE1E5a = gbsm(off, 10);
|
||
if(type == 1046) { // I/NAV
|
||
d_gm.BGDE1E5b = gbsm(off, 10);
|
||
}
|
||
else {
|
||
d_gm.BGDE1E5b = 9999999;
|
||
}
|
||
|
||
// thank you RTKLIB:
|
||
#if 0
|
||
setbitu(rtcm->buff,i,12,1045 ); i+=12;
|
||
setbitu(rtcm->buff,i, 6,prn ); i+= 6;
|
||
setbitu(rtcm->buff,i,12,week ); i+=12;
|
||
setbitu(rtcm->buff,i,10,eph->iode); i+=10;
|
||
setbitu(rtcm->buff,i, 8,eph->sva ); i+= 8;
|
||
setbits(rtcm->buff,i,14,idot ); i+=14;
|
||
setbitu(rtcm->buff,i,14,toc ); i+=14;
|
||
setbits(rtcm->buff,i, 6,af2 ); i+= 6;
|
||
setbits(rtcm->buff,i,21,af1 ); i+=21;
|
||
setbits(rtcm->buff,i,31,af0 ); i+=31;
|
||
|
||
setbits(rtcm->buff,i,16,crs ); i+=16;
|
||
setbits(rtcm->buff,i,16,deln ); i+=16;
|
||
setbits(rtcm->buff,i,32,M0 ); i+=32;
|
||
setbits(rtcm->buff,i,16,cuc ); i+=16;
|
||
setbitu(rtcm->buff,i,32,e ); i+=32;
|
||
setbits(rtcm->buff,i,16,cus ); i+=16;
|
||
setbitu(rtcm->buff,i,32,sqrtA ); i+=32;
|
||
setbitu(rtcm->buff,i,14,toe ); i+=14;
|
||
setbits(rtcm->buff,i,16,cic ); i+=16;
|
||
setbits(rtcm->buff,i,32,OMG0 ); i+=32;
|
||
setbits(rtcm->buff,i,16,cis ); i+=16;
|
||
setbits(rtcm->buff,i,32,i0 ); i+=32;
|
||
setbits(rtcm->buff,i,16,crc ); i+=16;
|
||
setbits(rtcm->buff,i,32,omg ); i+=32;
|
||
setbits(rtcm->buff,i,24,OMGd ); i+=24;
|
||
setbits(rtcm->buff,i,10,bgd1 ); i+=10;
|
||
|
||
1045: F/NAV
|
||
setbitu(rtcm->buff,i, 2,oshs ); i+= 2; /* E5a SVH */
|
||
setbitu(rtcm->buff,i, 1,osdvs ); i+= 1; /* E5a DVS */
|
||
setbitu(rtcm->buff,i, 7,0 ); i+= 7; /* reserved */
|
||
1046: I/NAV
|
||
setbits(rtcm->buff,i,10,bgd2 ); i+=10;
|
||
setbitu(rtcm->buff,i, 2,oshs1 ); i+= 2; /* E5b SVH */
|
||
setbitu(rtcm->buff,i, 1,osdvs1 ); i+= 1; /* E5b DVS */
|
||
setbitu(rtcm->buff,i, 2,oshs2 ); i+= 2; /* E1 SVH */
|
||
setbitu(rtcm->buff,i, 1,osdvs2 ); i+= 1; /* E1 DVS */
|
||
|
||
#endif
|
||
}
|
||
else if(type == 1059 || type == 1242) { // GPS/Galileo bias
|
||
int off = 0;
|
||
int msgnum = gbum(off, 12);
|
||
|
||
int gpstime = gbum(off, 20);
|
||
int uinterval = gbum(off, 4);
|
||
int mmi = gbum(off, 1);
|
||
int iodssr = gbum(off, 4);
|
||
int ssrprov = gbum(off, 16);
|
||
int ssrsol = gbum(off, 4);
|
||
int numsats = gbum(off, 6);
|
||
|
||
// cout <<"msgnum "<<msgnum<<" gpstime " << gpstime<<" numsats "<< numsats<<endl;
|
||
d_dcbs.clear();
|
||
for(int n=0; n < numsats; ++n) {
|
||
int gpsid = gbum(off, 6);
|
||
int numdcbs = gbum(off, 5);
|
||
// cout<<" "<< (type==1059 ? "G" : "E") <<gpsid<<" has "<<numdcbs <<" DCBs\n";
|
||
SatID id;
|
||
id.gnss = (type==1059 ? 0 : 2); // GPS or Galileo
|
||
id.sv = gpsid;
|
||
for(int m = 0 ; m < numdcbs; ++m) {
|
||
int sig = gbum(off, 5);
|
||
id.sigid = sig;
|
||
int dcb = gbsm(off, 14); // 0.01 meter
|
||
d_dcbs[id] = 0.01*dcb;
|
||
// cout<<" sig "<<sig <<" dcb " << dcb*0.01 << "\n";
|
||
|
||
/*
|
||
Indicator to specify the GPS signal and tracking mode:
|
||
0 - L1 C/A
|
||
1- L1 P
|
||
2- L1 Z-tracking and similar (AS on)
|
||
3 - Reserved
|
||
4 - Reserved
|
||
5 - L2 C/A
|
||
6 - L2 L1(C/A)+(P2-P1) (semi-codeless)
|
||
7 - L2 L2C (M)
|
||
8 - L2 L2C (L)
|
||
9 - L2 L2C (M+L)
|
||
10 - L2 P
|
||
11 - L2 Z-tracking and similar (AS on)
|
||
12 - Reserved
|
||
13 - Reserved
|
||
14 - L5 I
|
||
15 - L5 Q
|
||
>15 - Reserved.
|
||
*/
|
||
}
|
||
}
|
||
}
|
||
}
|