galmon/rtcm.cc

319 lines
9.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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 12 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.
*/
}
}
}
}