文章目录

  • RTCM消息的帧结构如下表所示
  • 消息体
  • Multiple Signal Message (MSM)
  • message header
  • Satellite Data 与 Signal Data



RTCM为国际海运事业无线电技术委员会,是国际标准组织,当我们打开RTCM的官方文档会看到以下小字,

DEVELOPED BY RTCM SPECIAL COMMITTEE NO. 104,这个特别委员会(

SC,SPECIAL COMMITTEE) 104 就是差分全球导航卫星系统。


SMEMA通讯协议 cmt通讯协议_信噪比

RTCM消息的帧结构如下表所示

  • RTCM消息的前导符(Preamble)由8个bit组成 11010011(0xD3)
  • Message Length,这个10bits的消息长度不包括前导符,保留位,消息长度和校验位的6个字节
  • CRC位3个字节的校验位,校验算法的输入位从前导符到变长数据体

消息体

上表中的Variable Length Data Message大小为0-1023个字节不等,这取决于具体的消息类型,另外对于同类型的消息,消息体的大小也不一定是相等的。对于1005,1006这样的定长消息,那么消息类型确定了,消息体的大小也就确定了。可是也有消息本身也是变长的,如观测值,这些消息的消息体长度不仅与收星数目有关系,如下表中的1004,(Ns就是number of sat的意思),再如MEM消息,则更加复杂,其大小还与signal有关系。

SMEMA通讯协议 cmt通讯协议_Mask_02

Multiple Signal Message (MSM)

MSM消息用于传送GNSS观测值,如伪距,载波相位,多普勒频移和信噪比等。这个消息很重要,也属于比较复杂的一个消息。这个消息可以认为对应于Rinex文件里的观测文件。

message header

SMEMA通讯协议 cmt通讯协议_gnss_03

下边这张表对应于上表中的第一个block,大多数DF(Data Field)是很好理解的,值得一提的是GNSS Satellite MaskGNSS Signal Mask这两个DF。

  • GNSS Satellite Mask,通过decode这个DF我们要得到两个信息。第一,消息中包含几颗卫星的观测值,后边的两个block中要用这个值做内循环,没有这个值是无法进行后边的decode的;第二,消息中包含哪几颗卫星的信息,这个bit位和卫星PRN的关系可以再表3.5-90中得知,另外几个卫星系统是一样的,所以这里就不贴了。
  • GNSS Signal Mask这个signal Mask也是很有用的,其对应关系在下边的表里可以查看。

SMEMA通讯协议 cmt通讯协议_Data_04


SMEMA通讯协议 cmt通讯协议_SMEMA通讯协议_05

SMEMA通讯协议 cmt通讯协议_gnss_06

Satellite Data 与 Signal Data

这两部分也是需要结合起来才有意义,只decode前边或者后边是没有意义的。简单来概括就是,RTCM格式的GNSS观测值分为三个resolution的DF,这三层DF要全部加到一起才是最终的观测值。,也就是说最终的伪距和载波相位通过以下公式计算,

伪距=DF397+DF398+DF400载波相位=DF397+DF398+DF401

SMEMA通讯协议 cmt通讯协议_SMEMA通讯协议_07


SMEMA通讯协议 cmt通讯协议_SMEMA通讯协议_08

SMEMA通讯协议 cmt通讯协议_SMEMA通讯协议_09


这部分通过rtklib也反映的比较清楚,

首先,decode这两个block中的观测值,

/* decode satellite data */
    for (j=0;j<h.nsat;j++) { /* range */
        rng  =getbitu(rtcm->buff,i, 8); i+= 8;
        if (rng!=255) r[j]=rng*RANGE_MS;
    }
    for (j=0;j<h.nsat;j++) {
        rng_m=getbitu(rtcm->buff,i,10); i+=10;
        if (r[j]!=0.0) r[j]+=rng_m*P2_10*RANGE_MS;
    }
    /* decode signal data */
    for (j=0;j<ncell;j++) { /* pseudorange */
        prv=getbits(rtcm->buff,i,15); i+=15;
        if (prv!=-16384) pr[j]=prv*P2_24*RANGE_MS;
    }
    for (j=0;j<ncell;j++) { /* phaserange */
        cpv=getbits(rtcm->buff,i,22); i+=22;
        if (cpv!=-2097152) cp[j]=cpv*P2_29*RANGE_MS;
    }

然后,将其组合得到最终的观测信息

/* pseudorange (m) */
    if (r[i]!=0.0&&pr[j]>-1E12) {
       rtcm->obs.data[index].P[idx[k]]=r[i]+pr[j];
    }
    /* carrier-phase (cycle) */
    if (r[i]!=0.0&&cp[j]>-1E12) {
        rtcm->obs.data[index].L[idx[k]]=(r[i]+cp[j])*freq/CLIGHT;
    }