[学习]RTKLib详解:ppp.c与ppp_ar.c

文章目录

RTKLib详解:ppp.c与ppp_ar.c

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

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


Part A: ppp.c


一、整体作用与工作流程

该代码实现了GNSS精密单点定位(PPP)算法,基于非差相位和伪距观测值进行卡尔曼滤波状态估计,该代码完整实现了PPP算法的所有核心环节,通过模块化设计将各个误差源独立处理,便于维护和扩展。主要流程包括:

  1. 状态时间更新:通过udstate_ppp更新接收机位置、钟差、对流层参数和相位偏差
  2. 观测方程构建:res_ppp计算理论距离与观测值的残差
  3. 卡尔曼滤波更新:通过filter函数进行状态估计更新
  4. 模糊度固定:pppamb尝试进行整周模糊度固定

具体的函数调用关系如下:
pppos udstate_ppp res_ppp filter pppamb udpos_ppp udclk_ppp udtrop_ppp udbias_ppp corrmeas satposs testeclipse ifmeas corr_ion initx detslp_ll detslp_gf initx initx initx prectrop satantpcv antmodel windupcorr tidedisp tide_solid tide_oload tide_pole


二、核心函数说明

1. pppos

c 复制代码
void pppos(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 功能:PPP主处理函数
  • 输入
    • rtk: RTK控制结构体
    • obs: 观测值数组
    • n: 观测值数量
    • nav: 导航数据
  • 处理流程
    1. 初始化状态向量
    2. 计算卫星位置和钟差
    3. 排除日食卫星观测值
    4. 多次迭代执行残差计算和滤波更新
    5. 更新解算状态和协方差矩阵

2. res_ppp

c 复制代码
int res_ppp(int iter, const obsd_t *obs, int n, const double *rs, 
            const double *dts, const double *vare, const int *svh,
            const nav_t *nav, const double *x, rtk_t *rtk, 
            double *v, double *H, double *R, double *azel)
  • 功能:计算观测残差和设计矩阵
  • 数学原理
    • 几何距离计算: r = ( x i s − x ) 2 + ( y i s − y ) 2 + ( z i s − z ) 2 r = \sqrt{(x^s_i - x)^2 + (y^s_i - y)^2 + (z^s_i - z)^2} r=(xis−x)2+(yis−y)2+(zis−z)2
    • 相位观测方程: ϕ = λ N + r + c ( d t r − d t s ) + T + I + ϵ \phi = \lambda N + r + c(dt^r - dt^s) + T + I + \epsilon ϕ=λN+r+c(dtr−dts)+T+I+ϵ
  • 输出
    • v: 残差向量
    • H: 设计矩阵
    • R: 观测噪声协方差

3. tide_solid

c 复制代码
static void tide_solid(const double *rsun, const double *rmoon, 
                      const double *pos, const double *E, double gmst, 
                      int opt, double *dr)
  • 功能:计算固体地球潮汐位移
  • 数学模型
    u = K 2 [ H 2 ( 3 2 cos ⁡ 2 θ − 1 2 ) − 3 L 2 a 2 ] + K 3 [ H 3 ( . . . ) ] u = K_2[H_2(\frac{3}{2}\cos^2\theta - \frac{1}{2}) - 3L_2a^2] + K_3[H_3(...)] u=K2[H2(23cos2θ−21)−3L2a2]+K3[H3(...)]
    其中 K n = G M r n + 1 R n K_n = \frac{GM}{r^{n+1}}R^n Kn=rn+1GMRn
  • 输入
    • rsun/rmoon: 日月位置向量
    • pos: 测站坐标
    • E: 坐标转换矩阵

4. prectrop

c 复制代码
static double prectrop(gtime_t time, const double *pos, const double *azel,
                      const prcopt_t *opt, const double *x, double *dtdx,
                      double *var)
  • 功能:精密对流层延迟模型
  • 数学模型
    T = m h ( θ ) Z H D + m w ( θ ) ( Z W D + G n cot ⁡ θ cos ⁡ α + G e cot ⁡ θ sin ⁡ α ) T = m_h(\theta)ZHD + m_w(\theta)(ZWD + G_n\cot\theta\cos\alpha + G_e\cot\theta\sin\alpha) T=mh(θ)ZHD+mw(θ)(ZWD+Gncotθcosα+Gecotθsinα)
  • 参数
    • m_h/m_w: 干湿映射函数
    • ZHD: 天顶静力学延迟
    • G_n/G_e: 水平梯度参数

5. corrmeas

c 复制代码
static int corrmeas(const obsd_t *obs, const nav_t *nav, const double *pos,
                   const double *azel, const prcopt_t *opt,
                   const double *dantr, const double *dants, double phw,
                   double *meas, double *var, int *brk)
  • 功能:电离层和天线校正
  • 处理流程
    1. 无电离层组合计算
    2. 天线相位中心校正
    3. 风化改正
    4. DCB偏差校正

6. udbias_ppp

c 复制代码
static void udbias_ppp(rtk_t *rtk, const obsd_t *obs, int n, const nav_t *nav)
  • 功能:相位偏差状态更新
  • 处理步骤
    1. LLI检测周跳
    2. 几何自由组合检测周跳
    3. 相位偏差初始化
    4. 相位-码一致性校正

三、数学原理补充

卡尔曼滤波更新公式

  1. 预测:

    • 状态转移: x ^ k ∣ k − 1 − = Φ k − 1 x k − 1 \hat{x}^-{k|k-1} = \Phi{k-1}x_{k-1} x^k∣k−1−=Φk−1xk−1
    • 协方差预测: P k ∣ k − 1 − = Φ k − 1 P k − 1 Φ k − 1 T + Q k − 1 P^-{k|k-1} = \Phi{k-1}P_{k-1}\Phi^T_{k-1} + Q_{k-1} Pk∣k−1−=Φk−1Pk−1Φk−1T+Qk−1
  2. 更新:

    • 卡尔曼增益: K k = P k ∣ k − 1 − H k T ( H k P k ∣ k − 1 − H k T + R k ) − 1 K_k = P^-{k|k-1}H^T_k(H_kP^-{k|k-1}H^T_k + R_k)^{-1} Kk=Pk∣k−1−HkT(HkPk∣k−1−HkT+Rk)−1
    • 状态更新: x ^ k = x ^ k ∣ k − 1 − + K k ( z k − H k x ^ k ∣ k − 1 − ) \hat{x}k = \hat{x}^-{k|k-1} + K_k(z_k - H_k\hat{x}^-_{k|k-1}) x^k=x^k∣k−1−+Kk(zk−Hkx^k∣k−1−)
    • 协方差更新: P k = ( I − K k H k ) P k ∣ k − 1 − P_k = (I - K_kH_k)P^-_{k|k-1} Pk=(I−KkHk)Pk∣k−1−

Saastamoinen对流层模型
Z H D = 0.002277 P 1 − 0.00266 cos ⁡ ( 2 ϕ ) − 0.00028 H ZHD = 0.002277 \frac{P}{1 - 0.00266\cos(2\phi) - 0.00028H} ZHD=0.0022771−0.00266cos(2ϕ)−0.00028HP

其中P为地面气压,φ为纬度,H为高程


四、代码特点

  1. 支持多系统(GPS/GLO/GAL/SBS)
  2. 提供多种电离层处理模式(广播星历/STEC/无模型)
  3. 包含完整的误差修正模型(潮汐/对流层/天线偏差)
  4. 实现了PPP-AR模糊度固定功能
  5. 支持动态/静态模式切换

Part B: ppp_ar.c


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

这段代码实现了精密单点定位(PPP)中的整数模糊度解析(AR)功能,主要目标是通过宽巷(Wide-Lane, WL)和窄巷(Narrow-Lane, NL)组合观测值,固定载波相位模糊度以提高定位精度。整体工作流程如下:

  1. LC(线性组合)观测值预处理:计算三频观测值的线性组合(如宽巷、窄巷组合),并进行噪声统计。
  2. 宽巷模糊度固定:通过双频组合的宽巷模糊度解析,利用几何无关模型和置信度验证。
  3. 窄巷模糊度固定:基于宽巷结果,采用四舍五入法(ROUND)或整数最小二乘法(ILS)进一步固定窄巷模糊度。
  4. 状态更新:将固定后的模糊度作为约束条件,更新系统状态和协方差矩阵。

详细函数调用关系如下所示。
pppamb average_LC fix_amb_WL is_depend fix_amb_ROUND / fix_amb_ILS sel_amb fix_sol filter


二、函数功能与参数说明

1. lam_LC(i, j, k)

  • 功能:计算线性组合的波长(m)。
  • 输入
    • i, j, k:频率系数(如 1,-1,0 表示 L1-L2 组合)。
  • 输出 :波长 λ LC = c i f 1 + j f 2 + k f 5 \lambda_{\text{LC}} = \frac{c}{i f_1 + j f_2 + k f_5} λLC=if1+jf2+kf5c。

2. L_LC(i, j, k, L)

  • 功能:计算载波相位线性组合(m)。
  • 输入
    • L[0], L[1], L[2]:L1/L2/L5 载波相位观测值(周)。
  • 输出 :组合值 L LC = i f 1 L 1 + j f 2 L 2 + k f 5 L 5 i f 1 + j f 2 + k f 5 L_{\text{LC}} = \frac{i f_1 L_1 + j f_2 L_2 + k f_5 L_5}{i f_1 + j f_2 + k f_5} LLC=if1+jf2+kf5if1L1+jf2L2+kf5L5。

3. P_LC(i, j, k, P)

  • 功能:计算伪距线性组合(m)。
  • 输入
    • P[0], P[1], P[2]:L1/L2/L5 伪距观测值(m)。
  • 输出 :组合值 P LC = i f 1 P 1 + j f 2 P 2 + k f 5 P 5 i f 1 + j f 2 + k f 5 P_{\text{LC}} = \frac{i f_1 P_1 + j f_2 P_2 + k f_5 P_5}{i f_1 + j f_2 + k f_5} PLC=if1+jf2+kf5if1P1+jf2P2+kf5P5。

4. var_LC(i, j, k, sig)

  • 功能:计算线性组合的噪声方差(m²)。
  • 输入
    • sig:原始观测值噪声(m)。
  • 输出 :方差 σ LC 2 = i 2 f 1 2 + j 2 f 2 2 + k 2 f 5 2 ( i f 1 + j f 2 + k f 5 ) 2 σ 2 \sigma^2_{\text{LC}} = \frac{i^2 f_1^2 + j^2 f_2^2 + k^2 f_5^2}{(i f_1 + j f_2 + k f_5)^2} \sigma^2 σLC2=(if1+jf2+kf5)2i2f12+j2f22+k2f52σ2。

5. conffunc(N, B, sig)

  • 功能:计算模糊度整数假设的置信度。
  • 输入
    • N:候选整数模糊度。
    • B:浮点解模糊度。
    • sig:模糊度标准差。
  • 输出 :置信度 P = ∑ i = 1 7 [ erfc ( i − x 2 σ ) − erfc ( i + x 2 σ ) ] P = \sum_{i=1}^7 \left[ \text{erfc}\left(\frac{i-x}{\sqrt{2}\sigma}\right) - \text{erfc}\left(\frac{i+x}{\sqrt{2}\sigma}\right) \right] P=∑i=17[erfc(2 σi−x)−erfc(2 σi+x)],其中 x = ∣ B − N ∣ x = |B-N| x=∣B−N∣。
  • 功能:对LC观测值进行滑动窗口平均。
  • 输入
    • rtk:RTK状态结构体。
    • obs:观测数据数组。
    • azel:卫星方位角仰角数组。
  • 输出 :更新 rtk->ambc 中的LC均值和方差。
  • 功能:固定宽巷模糊度。

  • 输入

    • sat1, sat2:卫星编号。
  • 输出

    • NW:固定后的整数宽巷模糊度。
  • 公式
    B W = Δ L C 0 ( 1 ) − Δ L C 0 ( 2 ) λ W L + δ b W L ( 1 ) − δ b W L ( 2 ) (无REV_WL_FCB) B_W = \frac{\Delta LC_0^{(1)} - \Delta LC_0^{(2)}}{\lambda_{WL}} + \delta b_{WL}^{(1)} - \delta b_{WL}^{(2)} \quad \text{(无REV\_WL\_FCB)} BW=λWLΔLC0(1)−ΔLC0(2)+δbWL(1)−δbWL(2)(无REV_WL_FCB)

    其中 δ b W L \delta b_{WL} δbWL 为宽巷小数周偏差(FCB)。

8. fix_amb_ROUND(rtk, sat1, sat2, NW, n)

  • 功能:通过四舍五入法固定窄巷模糊度。
  • 输入
    • NW:宽巷模糊度数组。
  • 输出 :更新状态向量 rtk->x 和协方差矩阵 rtk->P

9. fix_amb_ILS(rtk, sat1, sat2, NW, n)

  • 功能:通过整数最小二乘(ILS)固定窄巷模糊度。
  • 数学原理
    定义窄巷模糊度 B N L = c 1 λ 1 N 1 + c 2 λ 2 N 2 λ N L B_{NL} = \frac{c_1 \lambda_1 N_1 + c_2 \lambda_2 N_2}{\lambda_{NL}} BNL=λNLc1λ1N1+c2λ2N2,构造变换矩阵 D ,求解整数最小二乘问题:
    min ⁡ N ∈ Z n ∥ D − 1 ( B float − N ) ∥ Q 2 \min_{N \in \mathbb{Z}^n} \| D^{-1}(B_{\text{float}} - N) \|_Q^2 N∈Znmin∥D−1(Bfloat−N)∥Q2
    使用 LAMBDA 算法降维后进行比值检验(ratio-test)。
  • 主函数:协调整个模糊度解析流程。
  • 流程
    1. 计算LC观测值均值。
    2. 枚举卫星对,固定宽巷模糊度。
    3. 根据 modear 选择ROUND或ILS方法固定窄巷模糊度。

三、数学推导补充

1.宽巷与窄巷组合

  • 宽巷组合 (如 L1-L2):
    λ W L = c f 1 − f 2 ≈ 0.86   m \lambda_{WL} = \frac{c}{f_1 - f_2} \approx 0.86 \, \text{m} λWL=f1−f2c≈0.86m
  • 窄巷组合 (如 L1+L2):
    λ N L = c f 1 + f 2 ≈ 0.11   m \lambda_{NL} = \frac{c}{f_1 + f_2} \approx 0.11 \, \text{m} λNL=f1+f2c≈0.11m

2.整数最小二乘(ILS)

定义模糊度浮点解 N ^ ∈ R n \hat{N} \in \mathbb{R}^n N^∈Rn 及其协方差 Q Q Q,优化问题:
min ⁡ N ∈ Z n ∥ N ^ − N ∥ Q 2 \min_{N \in \mathbb{Z}^n} \| \hat{N} - N \|_Q^2 N∈Znmin∥N^−N∥Q2

通过 Cholesky 分解降维后搜索最近整数解,并验证比值 ∥ N ^ − N 2 ∥ Q 2 ∥ N ^ − N 1 ∥ Q 2 \frac{\|\hat{N}-N_2\|_Q^2}{\|\hat{N}-N_1\|_Q^2} ∥N^−N1∥Q2∥N^−N2∥Q2 是否超过阈值。


研究学习不易,点赞易。

工作生活不易,收藏易,点收藏不迷茫 :)


相关推荐
虾球xz34 分钟前
游戏引擎学习第263天:添加调试帧滑块
c++·学习·游戏引擎
.YM.Z1 小时前
C语言——操作符
c语言·开发语言·算法
柒柒的代码学习日记1 小时前
qsort函数
c语言
他们都不看好你,偏偏你最不争气2 小时前
OC语言学习——面向对象(下)
开发语言·学习·objective-c·面向对象
虾球xz2 小时前
游戏引擎学习第262天:绘制多帧性能分析图
c++·学习·游戏引擎
TUTO_TUTO2 小时前
【AWS+Wordpress-准备阶段】AWS注册+创建EC2实例
学习·云计算·aws
kkai人工智能3 小时前
DeepSeek的100个应用场景
人工智能·gpt·学习·chatgpt
J先生x3 小时前
【IP101】图像分割技术全解析:从传统算法到深度学习的进阶之路
图像处理·人工智能·深度学习·学习·算法·计算机视觉
秋山落叶万岭花开ღ3 小时前
C语言自定义类型:结构体详解
c语言
浩皓素4 小时前
探秘C语言中的递归:从基础概念到实战应用
c语言