RTCM 是一种普遍采用的数据传输格式,它是由国际海运事业无线电技术委员会提出的,用于制定在差分全球导航定位系统和实时动态操作时使用的标准。
表1 RTCM3.2标准格式的帧结构
序号 | 数据内容 | 比特数/bit | 备注 |
1 | 同步码 | 8 | 设为‘11010011’ |
2 | 保留 | 6 | 设为‘000000’ |
3 | 信息长度 | 10 | 数据信息的长度 |
4 | 数据信息 | 不定 | 最大1023bytes |
5 | CRC | 24 | 校验 |
RTCM3.X标准包含应用层﹑表示层、传输层、数据链路层以及物理层。对于编码﹑解码最重要的是表示层和传输层。表示层对整个数据结构做出了详细的定义,包含数据字段、消息类型等。传输层定义了传输的协议,校验方式等。RTCM3.X 为了达到较高的传输完整率,一条标准的电文由一个固定的引导字、保留字、一个消息的长度定义,一条消息和一个24 bits的周期冗余检校组成。
MSM电文组由于其通用性更好,便于编码、解码,未来将是实时GNSS 数据传输的重要方式。然而由于它是最新提出的一种电文类型,相关介绍文献也较少,因此下面对 MSM电文组进行介绍。MSM电文组由三部分组成﹐分别为电文头(Message Header),卫星数据(Satellite Data)和信号数据(Signal Data)。各MSM电文组的电文头是相同的,包含了该条消息的基本情况,通过解码电文头,可以得到消息类型,参考站信息﹐各观测值信息,电文长度等。
MSM电文组的信号数据是以Cell为单位进行排列,它的排列顺序根据GNSS Cell标志组(Masks)来排列的。GNSS Cell标志组是一个存放卫星编号及频率编号的二维数组。它的第一行存放的是卫星标志组中第一颗观测卫星各信号的标志,以此类推。因此它的大小Ncell是由卫星和信号的个数来决定的,Ncell= Nsat× Nsig,其中Nsat是卫星个数,Nsig是信号个数。
表3 各MSM电文组的消息头包含内容
完成项目中实时RTK部分两套代码的整合,结构体转换;完成单点定位分频点定位;完成完好性结构体数据的实时播发。
extern void ep2gtime(nav_Time_t * gt, double *ep)
{
gt->year = ep[0];
gt->month = ep[1];
gt->day = ep[2];
gt->hour = ep[3];
gt->minute = ep[4];
gt->sec = ep[5];
gpssecw(gt);
gtimejd(gt);
}
gtime_t navt2gtime(nav_Time_t *c)
{
gtime_t t = epoch2time(gpst0);
int week = c->week;
double sec = c->secw;
if (c->sec < -1E9 || 1E9 < sec) sec = 0.0;
t.time += 86400 * 7 * week + (int)sec;
t.sec = sec - (int)sec;
return t;
}
void gtime2navt(nav_Time_t *gt, gtime_t *ge)
{
double ep[6] = { 0 };
time2epoch(*ge, ep);
ep2gtime(gt, ep);
}
int sol2est(sol_t *sol, rtk_BslSol_t *BslSol)
{
return 1;
}
void link_free(nav_SatsEph_t *p_head)
{
nav_SatsEph_t *p_mov;
while (p_head != NULL)
{
p_mov = p_head->next;
p_head = p_mov->next;
free(p_mov);
}
}
int rtk2est(rtk_t *rtk, mnt_BslSol_t *est, rtksvr_t *svr,int fobs, mnt_ConstConfig_t *g_ConstConfig1, double *rs, double *dts, double *azel_,int nu,int nr, const obsd_t *obs)
{
int i;
sol2est(&rtk->sol, &est->BslSol);
for (i = 0; i < 3; i++)est->StaObs[0].StaInfos.PosXYZ[i] = rtk->rb[i];
for (i = 0; i < 3; i++)est->BslSol.bstaf.PosXYZ[i] = rtk->rb[i];
for (i = 0; i < 3; i++)est->BslSol.rstaf.PosXYZ[i] = svr->rtk.sol.rr[i];
obs2est(svr, est,fobs,rs,dts,azel_,nu,nr,obs, &svr->nav);
nav2est(svr, est);
return 1;
}
int initnav(mnt_BslSol_t *est)
{
est->NavInf.ephnum = 0;
nav_SatsEph_t *neph_t1 = NULL;
neph_t1 = est->NavInf.neph_t;
free(neph_t1);
}
int obs2est(rtksvr_t *svr, mnt_BslSol_t *est,int fobs, double *rs, double *dts, double *azel, int nu, int nr, const obsd_t *obs, nav_t *nav)
{
int i, j,k,index,bn=0,rn=0,sat,snr[NFREQ];
nav_Time_t nt;
sat_FrqInfo_t *p = est->StaObs->SatFrq;
est->StaObs[0].State = STA_ISOK;
est->StaObs[1].State = STA_ISOK;
strncpy(est->StaObs[0].StaInfos.StaName, svr->stream[0].msg + 14, 4);
strncpy(est->StaObs[1].StaInfos.StaName, svr->stream[1].msg + 14, 4);
memset(est->StaObs[0].SatObs, 0, sizeof(sat_ZdifObs_t)*MAXOBS);
memset(est->StaObs[1].SatObs, 0, sizeof(sat_ZdifObs_t)*MAXOBS);
est->StaObs[0].num = 0; est->StaObs[1].num = 0;
/*for (i = 0; i < fobs; i++) {
est->StaObs[0].SatNum = svr->obs[0][i].n;
est->StaObs[1].SatNum = svr->obs[1][0].n;*/
est->StaObs[0].SatNum = nr;
est->StaObs[1].SatNum = nu;
for (j = 0; j < nu; j++) {
/*if (dts[j * 2] == 0) continue;*/
est->StaObs[1].num += 1;
if (obs[j].sat <= NSATGPS + MAXPRNGLO) {
est->StaObs[1].SatObs[j].prn = obs[j].sat;
sat = est->StaObs[1].SatObs[j].prn;
est->StaObs[1].SatObs[j].sys = 'G';
est->StaObs[1].SatObs[j].sysid = 0;
}
else
{
est->StaObs[1].SatObs[j].sys = 'C';
est->StaObs[1].SatObs[j].sysid = 3;
est->StaObs[1].SatObs[j].prn = obs[j].sat + MIN_BDS_PRN - (NSATGPS + NSATGLO + 1);
sat = est->StaObs[1].SatObs[j].prn;
}
/*est->StaObs[0].SatObs[j].az = azel[j * 2];
est->StaObs[0].SatObs[j].el = azel[j * 2+1];*/
/*for (k = 0; k < 6; k++)est->StaObs[1].SatObs[j].sposvel[k] = rs[j * 6 + k];
est->StaObs[1].SatObs[j].sclk=dts[j*2];*/
gtime2navt(&est->StaObs[1].ObsTime, &obs[j].time);
for (k = 0; k < NFREQ; k++)snr[k] = obs[j].SNR[k] * 0.25;
for (k = 0; k < NFREQ; k++)est->StaObs[1].SatObs[j].snr[k] = snr[k];
strcpy(est->StaObs[1].SatObs[j].LLI, obs[j].LLI);
for (k = 0; k < NFREQ; k++)est->StaObs[1].SatObs[j].uL[k] = obs[j].L[k] * p->gnsslamb[sat][k];
for (k = 0; k < NFREQ; k++)est->StaObs[1].SatObs[j].uP[k] = obs[j].P[k];
}
for (j = 0; j < nr; j++) {
/*if (dts[j * 2 + nu * 2] == 0)continue;*/
est->StaObs[0].num += 1;
if (obs[j+nu].sat <= NSATGPS + MAXPRNGLO) {
est->StaObs[0].SatObs[j].prn = obs[j + nu].sat;
sat = est->StaObs[0].SatObs[j].prn;
est->StaObs[0].SatObs[j].sys = 'G';
est->StaObs[0].SatObs[j].sysid = 0;
}
else
{
est->StaObs[0].SatObs[j].sys = 'C';
est->StaObs[0].SatObs[j].sysid = 3;
est->StaObs[0].SatObs[j].prn = obs[j + nu].sat + MIN_BDS_PRN - (NSATGPS + NSATGLO + 1);
sat = est->StaObs[0].SatObs[j].prn;
}
gtime2navt(&est->StaObs[0].ObsTime, &obs[j + nu].time);
/*est->StaObs[1].SatObs[j].az = azel[j * 2+nu*2];
est->StaObs[1].SatObs[j].el = azel[j * 2 +1+nu*2];*/
/*for (k = 0; k < 6; k++)est->StaObs[0].SatObs[j].sposvel[k] = rs[j * 6+nu*6 + k];
est->StaObs[0].SatObs[j].sclk = dts[j * 2+nu*2];*/
for (k = 0; k < NFREQ; k++) snr[k]= obs[j + nu].SNR[k] * 0.25;
for (k = 0; k < NFREQ; k++)est->StaObs[0].SatObs[j].snr[k] = snr[k];
strcpy(est->StaObs[0].SatObs[j].LLI,obs[j + nu].LLI);
for (k = 0; k < NFREQ; k++)est->StaObs[0].SatObs[j].uL[k] = obs[j + nu].L[k] * p->gnsslamb[sat][k];
for (k = 0; k < NFREQ; k++)est->StaObs[0].SatObs[j].uP[k] = obs[j + nu].P[k];
}
/*}*/
return 1;
}
int nav2est(rtksvr_t *svr, mnt_BslSol_t *est)
{
int i,j,week;
nav_SatEph_t *ptr = NULL;
#define navall (NSATGPS + NSATGLO+ NSATCMP)
//nav_SatsEph_t* ptr = est->NavInf.neph_t;
nav_Time_t nt;
est->NavInf.leapsec=svr->nav.leaps;
est->NavInf.ephnum = 0;
for (i = 0; i < NSATGPS + NSATGLO+ NSATCMP; i++) {
ptr = (nav_SatEph_t*)(calloc(1, sizeof(nav_SatEph_t)));
if (ptr == NULL) {
return 0;
}
/*ptr->ephn = 2;*/
if (svr->nav.eph[i].sat <= 0|| svr->nav.eph[i].sat > NSATGPS + NSATGLO + NSATCMP) {
continue;
}
else
{
est->NavInf.ephnum+= 1;
}
if (svr->nav.eph[i].sat <= NSATGPS + MAXPRNGLO) {
ptr->sys = 'G';
ptr->prn = svr->nav.eph[i].sat;
}
else {
ptr->sys = 'C';
ptr->prn = svr->nav.eph[i].sat + MIN_BDS_PRN - (NSATGPS + NSATGLO + 1);
}
if (ptr->sys == 'G') {
svr->nav.eph[i].toe = gpst2time(svr->nav.eph[i].week, svr->nav.eph[i].toes);
svr->nav.eph[i].toc = gpst2time(svr->nav.eph[i].week, svr->nav.eph[i].toes);
gtime2navt(&ptr->tocgps, &svr->nav.eph[i].toe);
}
if (ptr->sys == 'C') {
//
svr->nav.eph[i].week = adjbdtweek(svr->nav.eph[i].week);
svr->nav.eph[i].toe = bdt2gpst_1(bdt2time(svr->nav.eph[i].week, svr->nav.eph[i].toes-14)); /* bdt -> gpst */
gtime2navt(&ptr->tocgps, &svr->nav.eph[i].toe);
bdt2gpst(&ptr->tocgps);
}
ptr->prn = ptr->prn;
ptr->clk_bias = svr->nav.eph[i].f0;
ptr->clk_drift = svr->nav.eph[i].f1;
ptr->clk_drate = svr->nav.eph[i].f2;
ptr->iode = svr->nav.eph[i].iode;
ptr->crs = svr->nav.eph[i].crs;
ptr->dltn = svr->nav.eph[i].deln;
ptr->m0 = svr->nav.eph[i].M0;
ptr->cuc = svr->nav.eph[i].cuc;
ptr->e = svr->nav.eph[i].e;
ptr->cus = svr->nav.eph[i].cus;
ptr->sqrtA = sqrt(svr->nav.eph[i].A);
ptr->toe = svr->nav.eph[i].toes;
ptr->cic = svr->nav.eph[i].cic;
ptr->omg0 = svr->nav.eph[i].OMG0;
ptr->cis = svr->nav.eph[i].cis;
ptr->i0 = svr->nav.eph[i].i0;
ptr->crc = svr->nav.eph[i].crc;
ptr->omg = svr->nav.eph[i].omg;
ptr->omgd = svr->nav.eph[i].OMGd;
ptr->idot = svr->nav.eph[i].idot;
ptr->l2c = svr->nav.eph[i].code;
ptr->week = svr->nav.eph[i].week;
ptr->l2p = svr->nav.eph[i].flag;
ptr->ura = /*svr->nav.eph[i].sva*/2;
ptr->svh = svr->nav.eph[i].svh;
ptr->tgd1 = svr->nav.eph[i].tgd[0];
ptr->tgd2 = svr->nav.eph[i].tgd[1];
ptr->iodc = svr->nav.eph[i].iodc;
ptr->tow = svr->nav.eph[i].toes;/*可能有问题*/
if (addseph(&est->NavInf, ptr) == 0) {
free(ptr);
}
/*ptr->next = NULL;
ptr = ptr->next;*/
}
return 1;
}
int est2svr(mnt_BslSol_t *est, rtksvr_t *svr)
{
int i;
est->BslSol.solut;
if (est->BslSol.solut.fixed == 1) {
svr->rtk.sol.stat = 1;
}
else
{
svr->rtk.sol.stat = 2;
}
for (i = 0; i < 3; i++)svr->rtk.sol.rr[i] = est->BslSol.solut.rovpos[i];
for (i = 0; i < 6; i++)svr->rtk.sol.qr[i] = est->BslSol.solut.stdpos[i];
svr->rtk.sol.age = est->BslSol.Age;
svr->rtk.sol.ratio = est->BslSol.ratio;
svr->rtk.sol.ns = est->BslSol.obspar.satvn;
svr->rtk.sol.gdop = 0.0;
return 1;
}
rtcm_t *rtcm = NULL;
rtcm=(rtcm_t*)calloc(1, sizeof(rtcm_t));
int sync = 0,index=0;
memcpy(&rtcm->WanHaoX, &est->WanHaoX, sizeof(Integrity));
gen_rtcm3(rtcm,1270,sync);
/*for(i=0;i<rtcm->nbyte;i++){
input_rtcm3(rtcm, rtcm->buff[i]);
}*/
strwrite(svr->stream + 3, rtcm->buff, rtcm->len+3);
strwrite(svr->stream + 4, rtcm->buff, rtcm->len+3);
free(rtcm);
int encode_type1270(rtcm_t *rtcm, int sync)
{
/*int i = 24;*/
//int i; i=sizeof(Integrity);
unsigned char *popt;
unsigned long len;
rtcm->WanHaoX.integrity_b.pvt_b.NVS[0] = 3;
popt = (unsigned char *)malloc(sizeof(Integrity) + 100);
len = compressBound(sizeof(Integrity));
setbitu(rtcm->buff, 24, 12,1270);
setbitu(rtcm->buff, 36, 4, 0);
if (compress(popt, &len, (unsigned char *)&rtcm->WanHaoX, (unsigned long)sizeof(Integrity)))
{
printf("compress ProOpt struct failed \n");
free(popt);
return 0;
}
if (len < sizeof(Integrity) + 100)
memcpy(rtcm->buff+5, popt, len);
else
{
printf("rrdp->ordp.ppp_buff越界");
}
rtcm->nbit = 40+len*8;
free(popt);
/*int st_len = sizeof(Integrity);
unsigned long len1 = st_len + 100;
unsigned char *buf;
buf = (unsigned char*)malloc(len1 * sizeof(char));
if (uncompress(buf, &len1, rtcm->buff + 5, (unsigned long)(rtcm->len - 5)) != 0)
{
printf("ucompress engine integrity struct failed \n");
free(buf);
return 0;
}
if (len1 == st_len)
memcpy(rtcm->WanHaoX, buf, len1);
free(buf);*/
return 1;
}