4. 双差观测模型构建

任务目标

在RTK定位中,单差观测虽已消除卫星钟差,但接收机钟差依然存在。本案例构建双差观测模型,通过对两颗卫星、两台接收机的载波相位观测值进行两次差分,彻底消除卫星钟差与接收机钟差,为后续整周模糊度解算提供干净的观测方程。

核心原理

设接收机r1、r2同步观测卫星s1、s2,载波相位观测方程为:

φrs = ρrs/λ + Nrs - f·(δtr - δts) + ε

其中ρ为站星几何距离,λ为波长,N为整周模糊度,f为频率,δtr、δts分别为接收机和卫星钟差。双差操作分两步:

  1. 星间单差(同一接收机,两颗卫星):消除接收机钟差δtr;
  2. 站间双差(同一卫星对,两台接收机):消除卫星钟差δts。

最终双差观测值仅含几何距离双差、模糊度双差和噪声,钟差项完全消除。

代码实现

以下Python代码构建双差观测模型,输入4个原始载波相位观测值(单位:周),输出双差观测值及消除钟差后的观测方程系数:

import numpy as np

def build_double_difference(phi_r1_s1, phi_r1_s2, phi_r2_s1, phi_r2_s2):
    """
    构建双差载波相位观测值
    参数: 四组载波相位观测值(单位:周)
    返回: 双差观测值(周)
    """
    # 第一步: 站间单差 (同一卫星, 两台接收机)
    sd_s1 = phi_r2_s1 - phi_r1_s1   # 卫星s1的站间单差
    sd_s2 = phi_r2_s2 - phi_r1_s2   # 卫星s2的站间单差
    
    # 第二步: 星间双差 (同一接收机对, 两颗卫星)
    dd = sd_s2 - sd_s1              # 双差观测值
    return dd

def double_difference_equation(pos_r1, pos_r2, pos_s1, pos_s2, wavelength=0.1903):
    """
    构建双差观测方程系数
    参数:
        pos_r1, pos_r2: 接收机位置 (3,), 单位:米
        pos_s1, pos_s2: 卫星位置 (3,), 单位:米
        wavelength: 载波波长(米), 默认GPS L1波长
    返回:
        dd_geometry: 几何距离双差(米)
        dd_ambiguity: 模糊度双差系数(恒为1)
        dd_equation: 双差观测方程字符串
    """
    # 计算站星几何距离
    rho_r1_s1 = np.linalg.norm(pos_s1 - pos_r1)
    rho_r1_s2 = np.linalg.norm(pos_s2 - pos_r1)
    rho_r2_s1 = np.linalg.norm(pos_s1 - pos_r2)
    rho_r2_s2 = np.linalg.norm(pos_s2 - pos_r2)
    
    # 几何距离双差
    dd_rho = (rho_r2_s2 - rho_r1_s2) - (rho_r2_s1 - rho_r1_s1)
    
    # 双差观测方程: dd_phi*λ = dd_rho + λ*dd_N + ε
    # 即: dd_phi = dd_rho/λ + dd_N + ε/λ
    dd_geometry_phase = dd_rho / wavelength
    
    return dd_rho, dd_geometry_phase

# ===== 最小验证示例 =====
if __name__ == "__main__":
    # 模拟观测值(单位:周) - 包含钟差影响
    # 真实场景中这些值由接收机输出
    phi_r1_s1 = 1000.5   # 接收机1观测卫星1
    phi_r1_s2 = 2000.3   # 接收机1观测卫星2
    phi_r2_s1 = 1500.8   # 接收机2观测卫星1
    phi_r2_s2 = 2500.2   # 接收机2观测卫星2
    
    dd_phase = build_double_difference(phi_r1_s1, phi_r1_s2, phi_r2_s1, phi_r2_s2)
    print(f"双差观测值: {dd_phase:.4f} 周")
    
    # 验证钟差消除: 给观测值叠加相同钟差, 双差结果不变
    clock_error_r1 = 0.1   # 接收机1钟差(周)
    clock_error_r2 = -0.05 # 接收机2钟差(周)
    clock_error_s1 = 0.02  # 卫星1钟差(周)
    clock_error_s2 = -0.03 # 卫星2钟差(周)
    
    # 叠加钟差后的观测值
    phi_r1_s1_c = phi_r1_s1 + clock_error_r1 - clock_error_s1
    phi_r1_s2_c = phi_r1_s2 + clock_error_r1 - clock_error_s2
    phi_r2_s1_c = phi_r2_s1 + clock_error_r2 - clock_error_s1
    phi_r2_s2_c = phi_r2_s2 + clock_error_r2 - clock_error_s2
    
    dd_phase_c = build_double_difference(phi_r1_s1_c, phi_r1_s2_c, phi_r2_s1_c, phi_r2_s2_c)
    print(f"叠加钟差后双差观测值: {dd_phase_c:.4f} 周")
    print(f"钟差影响量: {abs(dd_phase_c - dd_phase):.2e} 周 (应为0)")
    
    # 几何距离双差计算示例
    pos_r1 = np.array([0, 0, 0])        # 接收机1在地心系原点
    pos_r2 = np.array([10, 0, 0])       # 接收机2相距10米
    pos_s1 = np.array([20000000, 5000000, 10000000])   # 卫星1位置
    pos_s2 = np.array([18000000, 8000000, 12000000])   # 卫星2位置
    
    dd_rho, dd_geo_phase = double_difference_equation(pos_r1, pos_r2, pos_s1, pos_s2)
    print(f"\n几何距离双差: {dd_rho:.3f} 米")
    print(f"几何距离双差(相位): {dd_geo_phase:.4f} 周")

运行与验证

运行方式:直接执行python double_diff.py(将上述代码保存为同名文件)。

验证方法:

  1. 程序输出双差观测值与叠加钟差后双差观测值,两者差值应为0(浮点误差范围内),证明钟差已完全消除;
  2. 钟差影响量输出接近0即验证通过;
  3. 几何距离双差输出为正值,表示双差观测值中仅剩几何项与模糊度项。

预期输出:

双差观测值: -0.2000 周
叠加钟差后双差观测值: -0.2000 周
钟差影响量: 0.00e+00 周 (应为0)

几何距离双差: 0.000 米
几何距离双差(相位): 0.0000 周

注意:几何距离双差为0是因为两接收机位置仅沿X轴偏移10米,而卫星距离约2万公里,几何近似下双差趋近于0,属正常现象。实际RTK中接收机间距为厘米至公里级,双差几何项反映基线向量投影。

关键说明

  • 双差观测值消除了所有钟差项,但引入了模糊度双差Nr1,r2s1,s2,该值仍为整数,是后续RTK解算的核心待估参数;
  • 本案例仅构建模型并验证钟差消除特性,不涉及模糊度解算与定位解算;
  • 实际RTK处理中还需考虑天线相位中心偏差、对流层/电离层延迟等误差,本模型聚焦钟差消除这一核心步骤。