RTCM编解码学习及代码扩展

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;

}

  • 24
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: RTCM3.2解码程序是一种用于将RTCM3.2格式的数据转换为可读性高的信息的软件程序。RTCM(Radio Technical Commission for Maritime Services)是一个国际组织,负责制定和推广用于无线电通信的技术标准。 RTCM3.2是用于全球导航卫星系统(GNSS)的一种数据格式。这种格式包含了通过卫星信号传输的位置、速度和时间等相关信息。RTCM3.2解码程序旨在将这些信息解析出来,并以易于理解的方式呈现出来。 RTCM3.2解码程序通常由几个主要模块组成。首先,程序会读取并解析RTCM3.2数据流。然后,它会提取每个数据帧的相关信息,例如卫星的ID、接收机的坐标和时间戳等。接下来,程序会对数据进行处理,例如校正误差和生成精确的位置解算结果。 在解码完成后,程序通常会将结果显示在用户界面上。用户可以通过界面查看卫星的数量、精度等信息,也可以导出数据供其他应用程序使用。 RTCM3.2解码程序在各种应用中发挥着重要的作用。例如,在航空航天和定位导航领域,它可用于获取高精度的位置和速度信息。在地理测量和地图制作中,它可用于获取准确的地理坐标。此外,RTCM3.2解码程序还可用于定位服务、气象预报、海洋研究等领域。 总之,RTCM3.2解码程序是一种用于解析并处理RTCM3.2格式数据的软件工具,它能够提供高精度的位置、速度和时间等信息。无论在航空航天、地理测量还是其他领域,它都具有广泛的应用前景。 ### 回答2: RTCM3.2解码程序是一种计算机程序,用于解码RTCM3.2格式的数据。RTCM(Radio Technical Commission for Maritime Services)是一个制定标准的组织,旨在促进海事服务和卫星导航系统的发展和使用。 RTCM3.2是一种用于GPS和GNSS(全球导航卫星系统)接收机的数据格式标准,主要用于传输导航和定位数据。这种数据格式使用二进制编码,能够有效地传输大量的位置、速度和时间等信息。 RTCM3.2解码程序通过读取RTCM3.2格式的数据流,将其解析为可理解和使用的定位信息。它会将接收到的二进制数据解析为不同的数据字段,例如GPS卫星的编号、用于定位的卫星信号强度、接收机的位置和速度等。 解码程序还可以对数据进行校验,确保接收到的数据的完整性和正确性。一旦数据被成功解码,用户就可以使用解码后的信息进行定位和导航操作。 RTCM3.2解码程序在航海、船舶导航、航空以及地理信息系统等领域中发挥着重要作用。它帮助用户获取准确的位置和定位数据,提供导航支持,并应用于各种导航设备和应用中。 总的来说,RTCM3.2解码程序是一种用于解析RTCM3.2格式数据的计算机程序,能够将二进制数据解码为实际可用的位置和定位信息,为导航和定位提供支持。 ### 回答3: RTCM是一种用于实时差分全球定位系统(GNSS)的数据格式,而RTCM 3.2则是RTCM标准的一个版本。RTCM 3.2解码程序是一种软件程序,用于将接收到的RTCM 3.2数据进行解码和处理。 RTCM 3.2解码程序的主要功能包括以下几个方面: 1. 数据解析:程序能够从接收器接收到的原始RTCM 3.2数据中正确地解析出各种信息,包括卫星的位置、钟差、观测数据等。 2. 差分计算:解码程序能够根据接收到的差分基准站信息,对接收器的GNSS数据进行差分计算,以提高定位精度。 3. 数据处理:解码程序能够处理RTCM 3.2数据中的差分修正数值,并将其应用到GNSS数据中,以实现更准确的定位结果。 4. 输出结果:解码程序可以将解码和处理后的数据输出,以便用户使用或进一步分析。 此外,RTCM 3.2解码程序还可以具备一些附加功能,如数据压缩、周期性数据更新等,以提高数据传输效率和实时性。 RTCM 3.2解码程序主要应用于对GNSS定位精度要求较高的应用领域,如精密农业、测绘、地质勘探等。它能够帮助用户获得更高的定位精度,提高工作效率和数据质量。 总之,RTCM 3.2解码程序是一种能够解析和处理接收到的RTCM 3.2数据的软件程序,为用户提供更准确的定位结果和高质量的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值