[学习]RTKLib详解:ephemeris.c与rinex.c

RTKLib详解:ephemeris.c与rinex.c

本文是 RTKLlib详解 系列文章的一篇,目前该系列文章还在持续总结写作中,以发表的如下,有兴趣的可以翻阅。

[学习] RTKlib详解:功能、工具与源码结构解析
[学习]RTKLib详解:pntpos.c与postpos.c
[学习]RTKLib详解:rtkcmn.c与rtkpos.c
[学习]RTKLib详解:ppp.c与ppp_ar.c
[学习]RTKLib详解:ephemeris.c与rinex.c


PART A: ephemeris.c


一、代码整体作用与工作流程分析

1.1 整体作用

该代码实现卫星星历与钟差计算的核心功能,支持多种卫星导航系统(GPS/Galileo/QZSS/北斗/GLONASS/SBAS),提供从广播星历、精密星历到SSR(State Space Representation)校正的多级精度支持,该代码通过模块化设计实现了多系统兼容,采用迭代法保证计算精度,结合误差模型和校正机制满足不同应用场景需求。主要功能包括:

  • 卫星位置与速度计算(ECEF坐标系)
  • 卫星钟差与钟漂计算
  • 星历数据选择与有效性验证
  • 坐标系旋转与相对论效应修正
  • 误差方差建模(URA/SSR)
1.2 工作流程
EPHOPT_BRDC
EPHOPT_SBAS
EPHOPT_SSR
satposs
satpos
ephopt
ephpos
satpos_sbas
satpos_ssr
seleph/selgeph/selseph
eph2pos/geph2pos/seph2pos
ephpos + SBAS校正
ephpos + SSR校正
开普勒方程求解
SSR轨道/钟差修正

二、核心函数说明

2.1 alm2pos (Almanac to Position)

功能: 通过卫星历书计算概略位置
输入:

  • time: 当前时间(GPST)
  • alm: 阿尔曼历数据(alm_t结构体)
    输出:
  • rs: 卫星位置 [x,y,z] (m)
  • dts: 钟差 (s)
    数学原理:
  1. 计算平近点角 M = M0 + √(μ/A³) * tk
  2. 牛顿迭代法解开普勒方程 E = M + e·sinE
  3. 真近点角转换: ν = atan2(√(1-e²)sinE, cosE - e)
  4. 极坐标到直角坐标转换: r = A(1 - e·cosE)
2.2 eph2clk (Ephemeris to Clock)

功能: 广播星历钟差计算
输入:

  • time: 卫星时钟时间(GPST)
  • eph: 广播星历数据(eph_t结构体)
    输出:
  • 返回钟差 Δt = f0 + f1·t + f2·t²
    特性: 双次迭代消除时间依赖性
2.3 eph2pos (Ephemeris to Position)

功能: 广播星历卫星位置计算
数学流程:

M计算
开普勒方程迭代
轨道平面坐标
摄动修正
坐标系旋转
相对论修正

关键公式:

  • 开普勒方程:E = M + e·sinE (迭代收敛精度1e-14)
  • 相对论修正项:Δt_rel = -2√(μA)/c² * e·sinE
  • 坐标旋转矩阵:涉及升交点赤经Ω的时变特性

2.4 geph2pos (GLONASS Ephemeris)

特殊性:

  • 使用数值积分法解算轨道微分方程
  • 包含地球扁率J2和自转角速度Ω的摄动项
  • 微分方程形式:ẍ = [c+Ω²]x + 2Ωẏ + ax
2.5 satpos_ssr (SSR校正)

校正流程:

  1. 获取轨道偏差Δr [径向/切向/横向]
  2. 获取钟差校正Δt = dclk[0] + dclk[1]·t + dclk[2]·t²
  3. 天线相位中心修正
  4. 方差计算采用SSR URA模型

三、核心算法数学推导

3.1 开普勒方程求解

标准形式:
M = E − e sin ⁡ E M = E - e \sin E M=EesinE
牛顿迭代公式:
E n + 1 = E n − E n − e sin ⁡ E n − M 1 − e cos ⁡ E n E_{n+1} = E_n - \frac{E_n - e \sin E_n - M}{1 - e \cos E_n} En+1=En1ecosEnEnesinEnM
代码实现中设置最大迭代次数 30 30 30 次,相对容差 1 0 − 14 10^{-14} 1014

3.2 坐标系转换

从轨道坐标系到ECEF的转换矩阵:
[ cos ⁡ u − sin ⁡ u 0 sin ⁡ u cos ⁡ u 0 0 0 1 ] \begin{bmatrix} \cos u & -\sin u & 0 \\ \sin u & \cos u & 0 \\ 0 & 0 & 1 \end{bmatrix} cosusinu0sinucosu0001
结合升交点赤经 $ \Omega $ 的时变特性:
Ω = Ω 0 + ( Ω ˙ − ω e ) t − ω e t os \Omega = \Omega_0 + (\dot{\Omega} - \omega_e)t - \omega_e t_{\text{os}} Ω=Ω0+(Ω˙ωe)tωetos

3.3 SSR轨道校正

采用径向-切向-横向(Radial-Across-Along)分解:
Δ r ⃗ = e ⃗ r ⋅ Δ r radial + e ⃗ a ⋅ Δ r along + e ⃗ c ⋅ Δ r cross \Delta \vec{r} = \vec{e}_r \cdot \Delta r_{\text{radial}} + \vec{e}_a \cdot \Delta r_{\text{along}} + \vec{e}_c \cdot \Delta r_{\text{cross}} Δr =e rΔrradial+e aΔralong+e cΔrcross
其中 { e ⃗ r , e ⃗ a , e ⃗ c } \{\vec{e}_r, \vec{e}_a, \vec{e}_c\} {e r,e a,e c} 构成正交基矢量。

四、完整函数调用关系

satposs
satpos
satpos_sbas
satpos_ssr
ephpos
seleph
eph2pos
var_uraeph
ephpos + sbssatcorr
ephpos + SSR校正
var_urassr
selgeph
selseph
开普勒方程迭代
坐标旋转
相对论修正

五、误差模型

5.1 URA转换模型

var_uraeph:
ura_value = [ 2.4 , 3.4 , … , 6144.0 ] \text{ura\_value} = \left[2.4, 3.4, \dots, 6144.0\right] ura_value=[2.4,3.4,,6144.0]
var = { ( 6144.0 ) 2 if ura < 0  or ura > 15 ( ura_value [ ura ] ) 2 otherwise \text{var} = \begin{cases} (6144.0)^2 & \text{if } \text{ura} < 0 \text{ or } \text{ura} > 15 \\ (\text{ura\_value}[\text{ura}])^2 & \text{otherwise} \end{cases} var={(6144.0)2(ura_value[ura])2if ura<0 or ura>15otherwise

var_urassr:
std = { ( 3 ( ⌊ ura / 8 ⌋ ) ⋅ ( 1 + ( ura   m o d   7 ) / 4 ) − 1 ) × 1 0 − 3 if  0 < ura < 63 ( 5.4665 ) 2 if ura ≥ 63 ( 0.15 ) 2 if ura ≤ 0 \text{std} = \begin{cases} (3^{(\lfloor \text{ura}/8 \rfloor)} \cdot (1 + (\text{ura} \bmod 7)/4) - 1) \times 10^{-3} & \text{if } 0 < \text{ura} < 63 \\ (5.4665)^2 & \text{if } \text{ura} \geq 63 \\ (0.15)^2 & \text{if } \text{ura} \leq 0 \end{cases} std= (3(⌊ura/8⌋)(1+(uramod7)/4)1)×103(5.4665)2(0.15)2if 0<ura<63if ura63if ura0

5.2 SSR校正限幅
  • 最大轨道修正: 10   m 10 \, \text{m} 10m
  • 最大钟差修正: c ⋅ 1 0 − 6   m c \cdot 10^{-6} \, \text{m} c106m
  • 最大龄期:轨道 90   s 90 \, \text{s} 90s / 钟差 10   s 10 \, \text{s} 10s
5.3 相对论修正项

Δ t rel = − 2 c 2 μ A ⋅ e ⋅ sin ⁡ E \Delta t_{\text{rel}} = -\frac{2}{c^2} \sqrt{\mu A} \cdot e \cdot \sin E Δtrel=c22μA esinE

5.4 微分方程形式(GLONASS)

x ¨ = [ c + Ω 2 ] x + 2 Ω y ˙ + a x \ddot{x} = [c + \Omega^2]x + 2\Omega \dot{y} + a_x x¨=[c+Ω2]x+y˙+ax

5.5 SSR钟差修正

Δ t corr = Δ t clk + Δ r ⃗ radial c \Delta t_{\text{corr}} = \Delta t_{\text{clk}} + \frac{\Delta \vec{r}_{\text{radial}}}{c} Δtcorr=Δtclk+cΔr radial


六、系统特性处理

系统引力常数 $ \mu $地球自转角速度 $ \Omega $特殊处理
GPS 3.9860050 × 1 0 14 3.9860050 \times 10^{14} 3.9860050×1014 7.292115 × 1 0 − 5 7.292115 \times 10^{-5} 7.292115×105标准开普勒解算
GLONASS 3.9860044 × 1 0 14 3.9860044 \times 10^{14} 3.9860044×1014 7.292115 × 1 0 − 5 7.292115 \times 10^{-5} 7.292115×105数值积分法
Galileo 3.986004418 × 1 0 14 3.986004418 \times 10^{14} 3.986004418×1014 7.2921151467 × 1 0 − 5 7.2921151467 \times 10^{-5} 7.2921151467×105精密摄动模型
北斗GEO卫星 3.986004418 × 1 0 14 3.986004418 \times 10^{14} 3.986004418×1014 7.292115 × 1 0 − 5 7.292115 \times 10^{-5} 7.292115×105五度倾角坐标变换

PART B:rinex.c


一、整体作用与工作流程分析

该代码实现了一个RINEX(Receiver Independent Exchange Format)文件处理模块,主要用于GNSS(全球导航卫星系统)数据的读取、解析和输出,该代码通过模块化设计实现了复杂多系统的GNSS数据处理,其核心在于通过统一接口处理不同卫星系统的观测数据与导航数据,同时保持RINEX标准的兼容性。。其核心功能包括:

  • RINEX文件头解析与生成
  • 观测数据与导航电文的读取
  • 卫星星历解码
  • 相位偏移处理
  • 多系统(GPS/GLO/GAL/QZS/SBS/CMP)支持
  • 数据格式转换与输出

工作流程

Observation Data
Navigation Data
Input RINEX File
File Type
readrnxobs
readrnxnav
readrnxobsb
readrnxnavb
decode_obsdata
decode_eph
adjweek
Process Observations
Output Processed Data
outrnxobsb
Output RINEX File

二、函数详细说明

2.1 init_sta

功能:初始化测站参数结构体
输入参数

  • sta_t *sta:测站参数结构体指针
    输出参数
  • sta:初始化后的测站参数
2.2 sat2code

功能:将卫星编号转换为RINEX格式的卫星代码
输入参数

  • int sat:卫星编号(含系统标识)
  • char *code:输出缓冲区
    输出参数
  • code:格式如"G01" (GPS), “R24” (GLONASS)
    数学原理
    通过satsys()函数分离系统标识符(SYS_GPS/SYS_GLO等)和PRN编号,使用ASCII字符拼接。
2.3 adjweek

功能:调整时间以处理周跳问题
输入参数

  • gtime_t t:当前时间
  • gtime_t t0:参考时间
    输出参数
  • gtime_t:调整后的时间
    数学原理
    if  Δ t < − 302400 s ⇒ t = t + 604800 s if  Δ t > 302400 s ⇒ t = t − 604800 s \text{if } \Delta t < -302400s \Rightarrow t = t + 604800s \\ \text{if } \Delta t > 302400s \Rightarrow t = t - 604800s if Δt<302400st=t+604800sif Δt>302400st=t604800s
    其中 Δ t = timediff ( t , t 0 ) \Delta t = \text{timediff}(t, t_0) Δt=timediff(t,t0),确保时间连续性。
2.4 decode_eph

功能:解码GPS/北斗星历数据
输入参数

  • double ver:RINEX版本号
  • int sat:卫星编号
  • gtime_t toc:时钟参考时间
  • double *data:原始星历数据数组
    输出参数
  • eph_t *eph:填充后的星历结构体
    关键字段处理
  • 计算卫星健康状态(svh)、精度(sva)
  • 转换时间参数(toe, ttr)
2.5 uravalue & uraindex

功能:URA值与索引转换
数学关系
ura_value = { ura_eph [ i ] if  0 ≤ i < 15 32767 otherwise \text{ura\_value} = \begin{cases} \text{ura\_eph}[i] & \text{if } 0 \leq i < 15 \\ 32767 & \text{otherwise} \end{cases} ura_value={ura_eph[i]32767if 0i<15otherwise
ura_index ( x ) = min ⁡ { i ∣ ura_eph [ i ] ≥ x } \text{ura\_index}(x) = \min \left\{ i \mid \text{ura\_eph}[i] \geq x \right\} ura_index(x)=min{iura_eph[i]x}


三、函数调用关系图

Observation
Navigation
main
readrnx
file type
readrnxobs
readrnxnav
readrnxobsb
readrnxnavb
decode_obsdata
decode_eph
uraindex
adjweek
obsindex
save_slips
init_sta
init_rnxctr
malloc
free_rnxctr

四、关键算法解析

4.1 星历解码(decode_eph

北斗星历解码示例:

eph->iode = (int)data[3]; // AODE
eph->toes = data[11];     // Toe (s)
eph->week = (int)data[21]; 
eph->toe = bdt2gpst(bdt2time(eph->week, data[11])); 

将北斗时间(BDT)转换为GPS时间,并调整周跳。

4.2 相位偏移校正(set_index

通过配置选项(如-CL1C=1.5)设置相位偏移:

ind->shift[i] = shift; // 以cycle为单位

输出时应用偏移:

val[i] = str2num(...) + ind->shift[i];
4.3 多系统信号优先级
ind->pri[i] = getcodepri(sys, ind->code[i], opt);

根据系统(sys)和信号类型(code)确定观测值优先级,用于选择主观测值。


五、输出流程

Ver2
Ver3
Process Data
outrnxobsb
outrnxobsf
Output Type
Format Ver2
Format Ver3
%6d %02d %2.0f ...
%-3s %04.0f ...

研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)


### 关于RTKLIB `.trace` 文件中无星历数据 (`no ephemeris`) 的解决方案 当遇到`.trace`文件报告 `no ephemeris` 时,通常意味着RTKLIB未能成功解析卫星星历数据。这可能是由于输入观测数据或导航数据存在问题所致。以下是可能的原因及其对应的解决方法: #### 可能原因及解决办法 1. **导航文件缺失或不匹配** 如果未提供有效的导航文件(如RINEX格式的.nav文件),或者该文件的时间范围观测文件不符,则可能导致无法获取星历数据。 确保提供了正确的导航文件,并验证其时间戳是否覆盖了观测时间段[^1]。 2. **配置参数设置不当** 配置选项中的某些参数可能会阻止RTKLIB加载星历数据。例如,在`convbin`工具或其他后处理程序中,需确认已启用相应的选项来读取和存储星历信息。 使用命令行运行`rtkpost`时可以尝试调整如下关键参数: ```bash -p sol_format=0 # 设置输出解算格式为默认值(可选) -o output_file # 指定输出路径 ``` 3. **源码修改以增强日志记录功能** 若上述常规手段仍无法解决问题,可以通过自定义编译版本进一步排查问题根源。具体做法是在源代码层面增加额外的日志打印语句以便定位失败环节。参照已有实现逻辑,在涉及打开统计文件的部分加入更多细节描述: ```c /* 扩展后的状态跟踪部分 */ if (flag && sopt->sstat > 0) { strcpy(statfile, outfile); strcat(statfile, ".stat"); printf("Attempting to close previous stat file...\n"); // 新增提示消息 rtkclosestat(); printf("Opening new stat file at %s\n", statfile); // 显示实际操作对象名称 rtkopenstat(statfile, sopt->sstat); if (!check_ephemeris_loaded()) { // 假设新增辅助函数用于检测当前状况 fprintf(stderr, "[ERROR] No valid ephemerides found!\n"); } } ``` 上述改动有助于更直观了解执行流程以及潜在瓶颈所在位置[^4]。 4. **重新构建项目结构** 对于希望深入定制开发场景下的用户而言,按照官方文档指引完成整个工程环境搭建显得尤为重要。特别是针对不同平台特性适配过程中涉及到的具体步骤不可遗漏。比如通过CMakeLists.txt脚本管理依赖关系时应确保所有必要模块均被纳入考虑范围内: ```cmake set(DIR_SRCS "") aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS_RTKLIB) aux_source_directory(${PROJECT_SOURCE_DIR}/src/rcv DIR_SRCS_RCV) list(APPEND DIR_SRCS ${DIR_SRCS_RTKLIB}) list(APPEND DIR_SRCS ${DIR_SRCS_RCV}) add_library(rtklib STATIC ${DIR_SRCS}) target_include_directories(rtklib PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>) ``` 此外还需注意链接器标志位设定等问题以免引入不必要的副作用[^3]。 --- ### 总结 综上所述,“no ephemeris”的现象往往源于基础资料准备不足或是软件内部机制触发条件未满足两方面因素共同作用的结果。建议先从外部资源核查入手逐步缩小怀疑范围直至最终锁定确切诱因为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值