卫星信号模拟器(五):怎么证明你造的信号是对的——四道关卡

0 阅读5分钟

卫星信号模拟器(五):怎么证明你造的信号是对的——四道关卡

系列第五篇(终)。前面四篇把信号从场景一路造到了 DAC,这一篇回答最后一个问题:你怎么知道造出来的东西是对的? 不是"看起来像"就完了,而要像查案一样,一道关卡一道关卡地验。

1. 四道关卡,各验一层

关卡验什么判据能定位到哪一层的问题
频谱载波频率、调制体制中心频率对、BOC 双峰、载波被抑制载波 DDS、副载波、功率配比
捕获码相位、多普勒捕获峰明显、多普勒/码相位误差小测距码、多普勒计算
跟踪环锁定、无偏置PLL/DLL 鉴相器收敛到 0相位连续性、符号、正交关系
电文+定位编解码、几何一致性BCH/CRC 通过、ENU 误差 cm~dm电文编码、伪距、星历

原则:按顺序验,一道不过别进下一道。 每一关的问题都会以"症状"形式在上一关冒头,越早发现越省事。

2. 关卡一:频谱双峰

BOC 调制最鲜明的特征是频谱上主瓣被劈成两个、载波处塌陷。以 B1C 为例,中频 3.996 MHz:

  • BOC(1,1) 的两个主瓣骑在中频两侧:3.996 ± 1.023 MHz → 2.973 / 5.019 MHz
  • BOC(6,1) 的主瓣更靠外:3.996 ± 6.138 MHz → 2.142 / 10.134 MHz
  • 中频 3.996 MHz 处应该是"凹陷"(BOC 没有载波分量)

验证不需要全频段 FFT,算几个频点的能量就够了(Goertzel 单频检测,几十行):

// 对中频采样 buf[N],在频点 f 上做单频能量检测
double goertzel(const int8_t *buf, int N, double fs, double f)
{
    double w = 2 * PI * f / fs, c = 2 * cos(w);
    double q0 = 0, q1 = 0, q2 = 0;
    for (int n = 0; n < N; n++) {
        q0 = c * q1 - q2 + buf[n];
        q2 = q1; q1 = q0;
    }
    double re = q1 - q2 * cos(w), im = q2 * sin(w);
    return sqrt(re*re + im*im) / N;
}

实测一个正确的 B1C 信号,比值大致是:2.973/5.019 MHz(BOC11 主瓣)最强,2.142/10.134 MHz(BOC61)次之(因为只占 1/11 功率),3.996 MHz(载波)和噪声底相当。如果载波处出现一个高峰,说明副载波没加上;如果双峰位置不对,说明副载波频率错。

3. 关卡二:捕获

把信号丢进软件接收机跑一次捕获。看两样东西:

| Channel | PRN |  Frequency   | Doppler | Code Offset | Status |
|       1 |  23 |  3.99900e+06 |   3000  |    304733   |    T   |
|       2 |   6 |  3.99420e+06 |  -1800  |    127845   |    T   |
  • Doppler 要和你的理论值对得上(我们软件复现时,5 颗星的实测多普勒与计算值误差 ≤ 8 Hz);
  • Code Offset 要落在合理范围(一个码周期内),且捕获峰明显、旁瓣低。

判据:多普勒误差 ≤ 25 Hz、码相位误差 ≤ 2 个采样点。Doppler 对不上 → 多普勒符号或频率控制字算错;捕获不到 → 测距码错或 PRN 对不上。

4. 关卡三:跟踪

跟踪是"长期一致性"的照妖镜。看三张图:

图健康的样子有问题的样子
PLL 鉴相器(raw/filtered)快速收敛到 0,之后平贴 0有常数偏置、或慢慢漂走
DLL 鉴相器同上同上
相关值 I²+Q²稳定平台周期性塌陷(失锁)

常数偏置是最有诊断价值的信号:

  • PLL 有偏置 → 载波频率/相位关系错(比如 I/Q 符号搞反);
  • DLL 有偏置 → 码相位或群延迟错;
  • remCodePhase 线性漂移 → 码频率控制字有小误差。

(附带一个常见困惑:无噪声信号 C/N0 会飙到 80~90 dB-Hz,比真实信号高一倍——这是没加噪声导致的,不是 bug。要测灵敏度就加 AWGN。)

5. 关卡四:电文 + 定位

前两关过了,才轮到这关——因为它依赖的东西最多。

电文:BCH 校验通过、CRC-24Q 通过、解出来的星历字段与编码输入逐字段一致。这里推荐做一个"往返自检":把发送端编码的星历存一份,接收端解出来的比一份,任何比例因子、位宽、交织顺序的错误都会在这里现形。

定位:让接收机解算,看 ENU 误差:

预设坐标:(40°N, 116°E, 50 m)
解算结果:东向/北向/天向误差收敛到 cm~dm 级

定位是终极一致性检查——它同时依赖伪距、多普勒、电文、码、载波五样东西全部自洽。哪怕前面每一关都"看着对",只要伪距里有一个几米的系统性误差(比如漏了相对论改正、电离层符号反了、发射时刻没迭代),定位误差就会把它放大出来。

6. 一条心法:让"验证"也形成证据链

真正可靠的验证不是"跑一遍接收机能定位",而是多个独立来源互相印证。我们复现 B1C 时用了三件事交叉锁定测距码:

  1. 自己写的生成器 ↔ FPGA 的 Legendre ROM 逐位比对;
  2. 生成结果 ↔ ICD 表格的八进制码头锚点;
  3. 发送端编码 ↔ 接收端解交织的逆置换关系。

三条路都指向同一个结果,才敢说"码是对的"。单点验证只能证明"没崩",多点交叉才能证明"对"。

7. 小结(也是全系列的收尾)

把五篇串起来,就是一条完整的认知链:

场景 → 选星 → 伪距/多普勒 → 频率控制字 → 码/载波/副载波 → 调制合路 → DAC
                                                              ↓
定位误差 cm~dm  ←  四道关卡交叉验证  ←  频谱/捕获/跟踪/电文

卫星信号模拟器的难点,从来不在某一环有多高深,而在几百个参数要在码相位和载波相位的每一个 LSB 上都自洽。验证的意义,就是逼着你把这个"自洽"一层层钉死。