2022年8月

BDS 星历

字符偏移数据类型比例缩放名字单位描述
0U4-res1-保留
4U42-19sqram1/2卫星轨道半长轴的平方根
8U42-33es-卫星轨道偏心率
12I42-31ωπ近地点幅角
16I42-31M0π参考时间的平近点角
20I42-31i0π参考时间的轨道倾角
24I42-31Ω0π按参考时间计算的升交点赤经
28I42-43Ω̇π/s升交点赤经变化率
32I22-43Δnπ/s卫星平均运动速率与计算值之差
34I22-43IDOTπ/s轨道倾角变化率
36I42-31cucrad纬度幅角的余弦调和改正项振幅
40I42-31cusrad纬度幅角的正弦调和改正项振幅
44I42-6crcm轨道半径的余弦调和改正项振幅
48I42-6crsm轨道半径的正弦调和改正项振幅
52I42-31cicrad轨道倾角的余弦调和改正项振幅
56I42-31cisrad轨道倾角的正弦调和改正项振幅
60U423toes星历参考时刻
64U2-wne-参考时间的整周数
66U2-res2-保留
68U423tocs本时段钟差参数参考时间
72I42-33af0s卫星测距码相位时间偏移系数
76I42-50af1s/s卫星测距码相位时间偏移系数
80I22-66af2s/s2卫星测距码相位时间偏移系数
82I20.1tgdns星上设备时延差
84U1-iodc-时钟数据龄期
85U1-iode-星历数据龄期
86U1-ura-用户距离精度
87U1-health-卫星自主健康标识
88U1-svid-卫星编号
89U1-valid-信息可用标志(备注[1])
90U2-res3-保留

GPS 星历

字符偏移数据类型比例缩放名字单位描述
0U4-res1 保留
4U42-19sqra1/2卫星轨道半长轴的平方根
8U42-33es 卫星轨道偏心率
12I42-31ω 近地点幅角
16I42-31M0 参考时间的平近点角
20I42-31i0 参考时间的轨道倾角
24I42-31Ω0 按参考时间计算的升交点赤经
28I42-43Ω̇ 升交点赤经变化率
32I22-43Δnπ/s卫星平均运动速率与计算值之差
34I22-43IDOTπ/s轨道倾角变化率
36I22-29cucrad纬度幅角的余弦调和改正项振幅
38I22-29cusrad纬度幅角的正弦调和改正项振幅
40I22-5crcm轨道半径的余弦调和改正项振幅
42I22-5crsm轨道半径的正弦调和改正项振幅
44I22-29cicrad轨道倾角的余弦调和改正项振幅
46I22-29cisrad轨道倾角的正弦调和改正项振幅
48U224toes星历参考时间
50U2-wne-参考时间的整周数
52U424tocs本时段钟差参数参考时间
56I42-31af0s卫星测距码相位时间偏移系数
60I22-43af1s/s卫星测距码相位时间偏移系数
62I12-55af2s/s2卫星测距码相位时间偏移系数
63I12-31tgds星上设备时延差
64U2-iodc-时钟数据龄期
66U1-ura-用户距离精度
67U1-health-卫星自主健康标识
68U1-svid-卫星编号
69U1-valid-信息可用标志(备注[1])
70U2-res2-保留

NMEA的校验和

NMEA语句的校验和为'$'和'*'之间所有字符的异或和.

以下代码计算NMEA语句的校验和.

/*
 * Calculate nmea sentence's checksum
 * @buf:nmea sentence
 * @return: checksum
 */
unsigned char nmea_calc_checksum(const char *buf)
{
const char *p = buf;
unsigned char chs = 0;
​
while (*p == '$')   // skip '$'
p++;
while (*p != '*' && *p != 0)
chs ^= *p++;
​
return chs;
}

NMEA语句的校验和是否正确

/*
 * Check nmea sentence's checksum
 * @buf:buffer contains nmea sentence
 * @return: if checksum is okay return 1, else return 0
 */
int check_nmea(const char *buf) {
unsigned char chk = 0;
const char *p = buf;
char tmp[4];
​
while (*p == '$')
p++;
​
while (*p != '*' && *p != '\0')
chk ^= *p++;
​
if (*p == '*') {
sprintf(tmp, "%02X", chk);
return 0 == memcmp(tmp, p + 1, 2);
​
}
return 0;
}

NMEA中的经纬度

NMEA中经纬度格式为: ddmm.mmmm.
例如: 12023.4323, 表示120度23.4323分.
以下代码将NMEA经纬度字符串转化为度.

/*
 * Convert ddmm.mmmm format string into degrees
 * @s:  ddmm.mmmm format string in NMEA
 * @return: degree value 
 */
double convert_from_ddmm(const char *s)
{
double val = strtod(s, NULL);
int degrees = (int)val / 100;
double minutes = val - degrees * 100.0;
return degrees + minutes / 60.0;
}

导航状态消息

消息名称消息ID主要内容
NAV-STATUS01 00接收机导航状态.
NAV-DOP01 01定位精度因子.
NAV-SOL01 02ECEF坐标系下的PVT导航信息.
NAV-PV01 03大地坐标系下的位置与速度信息.
NAV-TIMEUTC01 10UTC时间信息.
NAV-CLOCK01 11时钟结算信息.
NAV-GPSINFO01 20GPS卫星信息.
NAV-BDSINFO01 21BDS卫星信息.
NAV-GLNINFO01 22GLONASS卫星信息.

NMEA格式的消息

语句名称语句ID主要内容
GGA4E 00UTC时间, 经纬度, 定位质量, HDOP, 海拔高度, 参与定位卫星数.
GLL4E 01经纬度, UTC时间, 定位模式.
GSA4E 02参与定位卫星的PRN编号, PDOP, HDOP, VDOP.
GSV4E 03可见卫星数, 卫星PRN编号, 仰角, 方位角, 载躁比.
RMC4E 04UTC时间, 经纬度, 定位模式, 速度, 航向, 日期.
VTG4E 05速度, 航向.
ZDA4E 08UTC时间, UTC日期.
GST4E 07伪距误差标准差RMS, 经纬高误差标准差.

GNSS 星历和年历

GNSS 星历和历书都构成了每颗卫星传输的导航信息。导航电文由 5 个子帧组成,每帧由 10 个单词组成,下载时间为 6 秒。
导航消息帧结构如下:

  • 子帧 1 - 3:星历
  • 子帧 4 - 5:年历 --> 完整年历需要 25 页才能完全下载。

因此,一帧 1-5 需要 30 秒才能下载。由于年历包含 25 页,因此下载年历所需的总时间为:25 页 30 秒/页 = 750 秒 = 12.5 分钟,也就是说15分钟更换星历和历书是比较合理的时间。另一方面,星历表需要 6 秒/子帧 5 个子帧 = 30 秒来下载。请注意,所有卫星的历书都是相同的,而星历表对每颗卫星都是唯一的。

星历和历书的目的是什么?

星历:

包含有关周数、卫星精度和健康状况、数据年龄、卫星时钟校正系数、轨道参数的信息 在星历(TOE)时间之前两小时和之后两小时有效。TOE 可以被认为是从 GNSS 控制段计算数据时 用于位置计算所需的实时卫星坐标计算。

年历:

包含的轨道信息不如星历表准确 有效期长达 90 天 用于将首次修复的时间加快 15 秒(与没有存储年历相比),也就是说历书不需要经常更换。

因此,接收器能够在没有年历的情况下计算位置。年历第一次帮助修复卫星,但仅此而已。然而,星历表对于定位计算至关重要。