我第一次在MATLAB里把LEO卫星链路的完整仿真跑通,看到星座图从一团高速旋转的乱码恢复成清晰的16QAM点阵时,确实有种“终于把理论串起来”的踏实感。这个项目本身并不是什么高深的算法创新,而是一条面向6G星地融合NTN场景的完整物理层仿真链路:发射端走OFDM,信道里加入LEO轨道运动引起的大动态多普勒,接收端依次做定时同步、CFO估计与补偿、信道估计、均衡,最后统计误码率。
这个仿真适合三类人:正在做卫星通信课程设计或毕业设计的同学,想快速搭一条NTN链路级仿真做验证的通信工程师,以及那些对6G空天地一体化感兴趣、但被多普勒建模劝退的入门者。读完这份总结,你会对整个链路的模块划分、LEO多普勒的计算方式、CFO估计和信道均衡的实现细节都心中有数,我还会把调试中踩过的坑一并写出来。
1. 链路整体设计:这条NTN仿真到底在仿真什么
1.1 为什么选择OFDM波形与120kHz子载波间隔
只要涉及6G和NTN的链路级仿真,OFDM基本是绕不开的选择。5G NR的地面网络已经全面采用OFDM,NTN作为6G空天地一体化的关键场景,在设计思路上延续了NR框架,这样做的最大好处是:地面基站和卫星用户之间的技术栈可以尽量统一,终端也不需要为卫星通信单独造一套完全不同的物理层。
但卫星信道和地面信道有一个根本区别——多普勒频移非常大。LEO卫星在低轨道上绕地球运动,轨道周期只有90分钟左右,地面用户看到的卫星相对速度可以达到每秒数公里。如果把频移直接叠加到OFDM符号上,会同时带来子载波间干扰(ICI)和公共相位误差(CPE),性能掉得很快。
OFDM解决多普勒问题有个非常直接的杠杆,就是加大子载波间隔。子载波间隔越宽,相同多普勒频移对应的归一化频偏就越小,系统能承受的多普勒能力就越强。硬件条件受限时,很多NTN链路会采用15kHz或30kHz间隔,但实际系统里5G NR已经定义了120kHz、240kHz甚至480kHz的扩展子载波间隔,专门给高速运动场景和高频段使用。我这个仿真选的是120kHz子载波间隔,主要原因有两个:一是它能覆盖LEO中低轨场景下绝大多数多普勒频移范围,二是FFT尺寸不用开得特别大,仿真跑起来不至于太慢。
OFDM配合循环前缀(CP)还有一个好处:它天然对多径时延有一定耐受力,能够把宽带信道转换成一组并行窄带子信道,这样接收端在做信道均衡时,只需要对每个子载波乘一个复系数,而不用做复杂的时域均衡。这在NTN这种大时延、大动态的场景里,工程实现上要友好得多。
1.2 NTN链路仿真包含的模块划分
整个仿真链路可以分成发射机、信道、接收机三大部分。我先用一张表把模块列出来,后面再逐一展开。
| 模块 | 具体内容 | 作用 |
|---|---|---|
| 发射端 | 随机比特生成、QPSK/16QAM调制、导频插入、OFDM调制(IFFT+添加CP) | 把信息比特变成适合信道传输的基带信号 |
| 卫星信道 | 自由空间路径损耗、Rician衰落、LEO运动引入的时变多普勒频偏 | 模拟星地链路对信号的主要损伤 |
| 接收端 | 定时同步、CFO估计与补偿、去CP/FFT、信道估计、均衡、解调、误码统计 | 把接收信号恢复成可靠的比特流 |
接收端是整个仿真的核心难点。拿到一帧接收信号后,你首先要判断OFDM符号从哪里开始,这就是定时同步;然后LEO高速运动导致载波频率偏移,你需要先估出来再补掉;补完频率后,信号才能正常做FFT;做完FFT之后,虽然频率偏移被校正,但信道本身的幅度和相位响应还不知道,所以要用导频做信道估计;最后把估计出来的信道响应用于均衡,才能把星座点拉回正确位置。
需要注意的是,这条链路里没有把编解码放进去。有信道编码的情况下,误码率曲线会低很多,但会掩盖物理层链路本身的一些细节问题。做NTN信道仿真,我倾向于先不加编码,用“裸调制”方式把MIMO信道、同步、补偿这类物理层问题看清楚了,再加编码也不迟。
1.3 链路级仿真的输入输出与评价指标
链路的输入是随机比特,输出是解调后的比特,二者对比就能得到误码率(BER)。除BER之外,我还会同时观察接收端星座图、信道估计结果的MSE(均方误差)、残余频偏值这三个辅助指标。原因很简单:BER只能告诉你“好不好”,却不能告诉你是哪个环节出了问题。如果星座图呈环形扩散,多半是残余频偏没补干净;如果星座图正常但误码率高,则大概率是信道估计不够准,需要换MMSE或调导频密度。
仿真参数上,我采用了一组比较接近5G NR NTN实际配置的参数:载波频率28GHz(Ka波段),子载波间隔120kHz,FFT点数为2048,循环前缀长度取512采样点。这套参数并不追求极致精度,而是让每个模块都处于“算法效果能看清楚”的状态。
2. LEO卫星信道与多普勒建模,这一关过了链路就成功一半
2.1 LEO轨道参数与相对运动
LEO卫星轨道高度一般在400km到1200km之间。我这次仿真选了600km,这是当前各大低轨星座项目里比较常见的高度。根据开普勒定律,圆轨道上的卫星运行速度可以近似用下面的公式计算:
v = sqrt(μ / (R + h))
其中μ为地球引力常数,约3.986 × 10^14 m³/s²;R为地球平均半径,约6371km;h为轨道高度。代入600km:
v = sqrt(3.986e14 / (6.371e6 + 6e5)) ≈ 7.56 km/s
这个速度很快,但这里需要特别强调一点:真正影响多普勒频移的并不是卫星在轨道上的绝对速度,而是卫星相对地面用户终端的径向速度分量。卫星在星下点正上方时,径向速度约等于0,此时多普勒频移很小;卫星从地平线附近出现或消失时,径向速度接近最大,多普勒频移也最大。因此,在多普勒建模时,不能简单地用一个恒定频偏,而应当把径向速度随用户仰角的变化考虑进来。
如果用简化的几何模型,可以假设卫星匀速直线飞过用户上方,用户看到的径向速度近似为v_r = v·cos(仰角变化),其中仰角随时间变化。仿真中可以把它简化为一段线性或余弦变化的多普勒曲线,分块更新。对于链路级仿真来说,这种简化已经能反映真实场景中多普勒动态变化的主要特征。
2.2 多普勒频移的定量计算
多普勒频移的计算公式非常简洁:
fd = v_r × f / c
其中,f为载波频率,c为光速,v_r为相对径向速度。把28GHz载波和7.5km/s的天顶附近相对速度代入,最大频移大约是700kHz。实际场景中用户看到的卫星仰角不会一直处于最恶劣状态,典型径向速度取3~6km/s更常见,对应的多普勒频移约在280kHz到560kHz之间。
这个值放到OFDM系统里看,就能理解为什么子载波间隔必须加大。若采用15kHz子载波间隔,500kHz频移相当于33个子载波间隔,整个子载波排列会被彻底破坏;而采用120kHz子载波间隔时,500kHz只对应约4.2个子载波间隔,虽然依然很严重,但算法上可以通过整数倍频偏校正加小数倍频偏补偿来处理。
我在仿真里还列了一张不同轨道高度和载波频率下的多普勒对照表,方便快速理解量级。
| 轨道高度 | 星载频段 | 载波频率 | 最大多普勒(粗略) |
|---|---|---|---|
| 600km | L频段 | 2GHz | 约50kHz |
| 600km | Ka频段 | 28GHz | 约700kHz |
| 1200km | Ka频段 | 28GHz | 约500kHz |
| 1200km | Q/V频段 | 48GHz | 约850kHz |
高频段方向,多普勒频移越来越大,这也是6G NTN仿真必须把多普勒补偿算法做好做扎实的原因。
2.3 大尺度与小尺度衰落建模
NTN信道和地面通信信道差异很大。卫星到地面主要是一条强视距(LOS)路径,散射体很少,因此小尺度衰落更多表现为随机的波动叠加在强直射径上。常见的选择是Rician信道模型,K因子(直射径功率与散射径功率之比)在户外场景下通常取10dB到20dB,比地面城区信道的K因子高很多。
信道模型在仿真里的作用是给每个子载波提供一个包含幅度和相位的复增益。对OFDM系统来说,我会在每个资源格上生成一个快照:
H(k) = sqrt(K/(K+1)) · H_LOS + sqrt(1/(K+1)) · H_NLOS
其中H_LOS是确定的直射分量,H_NLOS是服从标准复高斯分布的随机散射分量。这个公式保证了总功率归一化。卫星信道的多径数目很少,一般主径加2到3条弱径就足够模拟了,如果设置太多径反而会偏离NTN信道特点。
大尺度衰落方面,自由空间路径损耗按弗里斯公式计算:
PL = 20·log10(d) + 20·log10(f) - 147.55
600km轨道高度、用户仰角30度左右时的斜距大概在1200km量级,代入28GHz后,路径损耗约在180dB。这个数值大得吓人,但实际链路预算中会通过卫星天线的波束增益和地面终端的接收增益来弥补一部分。仿真处理比较简单:不直接逐采样点乘这个巨大损耗,而是把它折算成接收端的等效信噪比。链路里设置SNR为10dB到30dB,相当于已经扣除大尺度损耗后的参考值。
3. 接收端同步与多普勒补偿:先稳住时间和频率
3.1 帧同步:利用重复序列做粗定时
接收端第一件事是找到OFDM符号边界。我采用Schmidl-Cox算法的简化版本,核心思路是利用训练序列的重复结构做自相关。定义一个时间窗口,滑动计算前后两段长度为D的信号的相关峰,相关峰出现的位置就是符号起点。
相关度量可以用下面的方式计算:
P(d) = |Σ r(d+n)·conj(r(d+n+D))|² / (Σ|r(d+n)|² · Σ|r(d+n+D)|²)
代码实现起来很直接:
% 简化的Schmidl-Cox粗定时同步 D = 512; % 重复序列长度 windowLen = length(rxSig) - 2*D; metric = zeros(1, windowLen); for d = 1:windowLen numerator = abs(sum(conj(rxSig(d:d+D-1)) .* rxSig(d+D:d+2*D-1))).^2; denominator = (sum(abs(rxSig(d:d+D-1)).^2) + eps) * ... (sum(abs(rxSig(d+D:d+2*D-1)).^2) + eps); metric(d) = numerator / denominator; end [~, coarsePos] = max(metric);这里用乘积的平方和做分母是为了归一化,防止信号幅度波动影响峰值判决。对NTN这类信号幅度受大尺度衰落影响较大的场景,归一化非常重要。
实际操作中,我还会再加一个门限判定而不是直接取全局最大值。如果信噪比很低,或者频率偏移多大导致相关峰值下降,直接取最大值容易误判到噪声峰值上。设置“超过门限且维持连续若干帧稳定”的判据,比单纯找峰值更稳。定时同步不需要做到整数采样级别的精准,后续的信道估计会吸收一部分残余定时偏差,但偏差太大时依然会比较麻烦,这个我在后面问题章节专门讲。
3.2 小数倍CFO估计:Moose法的实现细节
频率同步是LEO链路里最需要抠细节的地方。载波频偏CFO按大小可以分成两部分:小于半个子载波间隔的小数倍频偏,以及整数倍子载波间隔的整数倍频偏。两者必须分开处理,因为小数倍频偏会导致子载波间干扰,而整数倍频偏等价于频域子载波的循环移位,处理方式完全不同。
小数倍频偏我优先用Moose算法,它结构简单,只需要两段相同的训练序列。假设训练序列长度为D,接收信号两段分别为r1和r2,理想情况下r2 = r1·exp(j2πΔf·D·Ts),所以共轭相关的相位包含了频偏信息:
Δf = angle(Σ conj(r1)·r2) / (2π·D·Ts)
代码如下:
% Moose CFO估计,输入rx为两段重复序列 D = 512; % 重复段长度 Ts = 1 / fs; % 采样周期 corr = sum(conj(rx(1:D)) .* rx(D+1:2*D)); hat_cfo = -angle(corr) / (2 * pi * D * Ts);Moose估计的频偏范围是 ±1/(2D·Ts),也就是相邻两段之间的相位差不能超过±π,否则会相位模糊。这里有一个非常实用的规律:D越小,可估计范围越大,但精度越低;D越大,精度越高,但范围越窄。做LEO仿真时,D的选择必须结合子载波间隔和最大多普勒频移一起考虑,这一点非常容易踩坑,后文详述。
在信噪比不算太差的时候,Moose估计的精度已经够用。如果后续还需要更高精度,可以在频域做二次细估计,比如在解调导频符号后利用导频的相位残差做个性别校正,但对于链路级验证来说,Moose加整数倍校正的组合已经能把残余频偏压到很低。
3.3 整数倍频偏校正与整体补偿
当我们把归一化频偏除以子载波间隔,得到的小数部分用于Moose估计,整数部分则表现为频域子载波的循环移位。比如归一化频偏是4.2个子载波,那么0.2由Moose处理,4个子载波的移位则需要通过整数倍频偏校正来恢复。
整数倍频偏估计有两种常用思路。第一种是时域方法,把LTE PSS/SSS或NTN同步序列与本地序列做互相关,看相关峰的位置推测移位量。第二种是频域方法,直接用导频符号在频域做相关,将接收导频循环移位若干子载波后与本地导频求相关,相关值最大处对应的移位就是整数倍频偏。
我在仿真里用的是频域导频相关法。因为信号做完FFT后,如果存在整数倍子载波频偏,数据子载波会整体移到错误的位置,此时接收导频序列与本地导频序列的相关性在正确移位量处会出现明显峰值。这个方法的优点是实现简单、计算量小,只需要把导频子载波单独扣出来跑一次互相关。
多普勒补偿本身有两种实现方式。第一种是直接在时域乘一个相位旋转因子exp(-j2πΔf·t),把整个接收信号搬回零频附近;第二种是在OFDM解调之后,对小残余频偏造成的相位旋转用数据导频做相位跟踪补偿。实际链路中两种方法会同时使用:先时域粗补偿把大频偏拉回来,再去CP做FFT,最后用导频跟踪残余相位。
时域补偿的时候,如果多普勒是时变的,还得分块更新频偏值。LEO卫星过顶的时间有限,多普勒变化率高,不能像静止场景那样一帧只用一个频偏。我的做法是把一帧分成若干块,每块估计一个CFO并做分段补偿,块长度设为若干个OFDM符号,这样既照顾了时变特性,又不会带来过大的计算开销。
% 分块时变多普勒补偿示意 for blk = 1:numBlocks idx = (blk-1)*blockLen+1 : blk*blockLen; t = (0:blockLen-1)/fs; rxSig(idx) = rxSig(idx) .* exp(-1j*2*pi*CFO_est(blk)*t); end这种分块补偿方式在工程上很常见,跟你在地面高速移动场景里做的自动频率控制(AFC)思路一致,只是LEO场景下频偏变化速度更快,块不能开太大。
4. 信道估计与均衡:把衰减和残余频偏的影响压下去
4.1 基于导频的LS信道估计与插值
频率补偿结束之后,信号经过FFT进入频域处理。此时数据可以近似等效为:
Y(k) = H(k)·X(k) + N(k)
接下来的问题就是:如何从接收信号Y(k)中恢复出发送符号X(k)。第一步要先把信道响应H(k)估计出来。
最基础的方法是LS(最小二乘)估计。只要在已知子载波位置插入导频,就用接收导频除以本地导频得到该点的信道响应:
H_ls(k_p) = Y(k_p) / X_pilot(k_p)
代码实现就是逐导频相除:
% LS信道估计:pilotIdx为导频子载波索引 H_ls = rxPilot ./ localPilot;LS估计的问题是它对噪声特别敏感——导频位置的接收信号如果被噪声污染,估计出的信道响应也会有噪声。所以在实际仿真里,我不会直接把LS结果用于均衡,而是先做一次插值,把只有导频位置的H扩展到所有数据子载波。
导频插值常用的有线性插值和三次样条插值。线性插值实现简单,性能在导频间隔较密时足够好;导频间隔较宽时建议用三次插值,性能提升更明显。但要注意,插值无法消除LS估计本身的噪声放大问题。如果想要更干净的信道估计,就需要DFT降噪或者MMSE估计。
4.2 DFT降噪与MMSE估计
DFT降噪是非常经典的一种LS增强方法。它利用信道冲激响应的能量只集中在前几条径上的特性,把频域LS估计结果做IFFT变换回时域,只保留前面若干条主径,把后面的噪声置零,再变换回频域。这个操作相当于把频域噪声的扩散效应压缩到时域窗内,信噪比越高、信道径越少,效果越好。
% DFT降噪:L为信道冲激响应保留长度 h_tmp = ifft(H_ls); h_tmp(L+1:end) = 0; H_df = fft(h_tmp);用DFT降噪时,L的取值很关键。取得太小会把真实的多径能量也丢掉,取得太大则噪声压制效果不明显。NTN信道的主径数量本身很少,L取CP长度的一到两成就差不多了。我在600km LEO+Rician信道下用L=32(总FFT 2048),效果就很理想。
MMSE信道估计在理论上比LS更优,因为它把噪声方差和信道统计信息都考虑进去了。MMSE估计的核心公式为:
H_mmse = R_HH · (R_HH + σ²·I)^(-1) · H_ls
其中R_HH是信道频域相关矩阵,σ²是噪声方差。问题是这个公式涉及矩阵求逆,FFT为2048时矩阵维数就是2048×2048,直接求逆在仿真里面还能接受,放到工程实现里完全不现实。所以实际工程中要么用低维近似,要么简化成对角/带状矩阵。
仿真中我做MMSE估计时会先用一个小规模子载波组来计算,而不是对全部子载波做完整矩阵运算。这样既能看到MMSE相对LS的性能增益,又不至于让仿真时间不可接受。综合来看,我最终信道估计算法选择的是“LS + DFT降噪 + 三次插值”,性能接近MMSE但实现简单得多,适合作为NTN链路初版验证方案。
4.3 均衡器的实现与对比
信道估计完成之后,均衡器负责把信道产生的幅度和相位失真补偿回来。常用的两种均衡算法是ZF(迫零)和MMSE。
ZF均衡实现最直接,就是数据子载波除以估计出的信道响应:
X_zf(k) = Y(k) / H_est(k)
它的缺点是当信道响应接近零时,除法会把噪声放大得很厉害。OFDM系统在高SNR下问题不大,但在低SNR或信道深衰落子载波上,ZF的误码性能会明显下降。
MMSE均衡则在补偿信道的同时考虑了噪声抑制,表达式为:
X_mmse(k) = conj(H_est(k)) · Y(k) / (|H_est(k)|² + σ²)
其中σ²是等效噪声方差。MMSE均衡的公式看起来比ZF复杂,但代码实现只多了一行噪声方差加法:
% MMSE均衡 x_mmse = conj(H_est) .* rxData ./ (abs(H_est).^2 + sigma2);这里噪声方差的估计非常关键。如果σ²估大了,均衡结果会偏向噪声抑制而牺牲信道补偿,星座点会整体向内收缩;估小了则退化为ZF。仿真中可以直接用导频位置估计噪声方差:
noiseVar = mean(abs(rxPilot - H_est(pilotIdx) .* localPilot).^2);从我的实测结果看,在16QAM、SNR高于15dB时,ZF和MMSE差距不大;一旦SNR降到10dB以下,MMSE的优势就非常明显。对于NTN这种链路预算紧张、高动态场景,我建议直接用MMSE,计算量增加很少,误码性能却更稳定。
5. 仿真结果对比与参数表:直接抄作业的配置
5.1 未补偿与补偿后的星座图与BER差异
如果不做任何多普勒补偿,直接把接收信号去做FFT和均衡,结果非常惨烈。28GHz载波、600km轨道高度下,即使取一个中等偏低的频偏值300kHz,对应的归一化频偏在120kHz子载波间隔下是2.5个子载波,这意味着星座点不仅整体旋转,还会严重混叠,16QAM解调结果完全不可用,BER差不多在0.4到0.5之间,等于随机猜。
执行完整的定时同步、CFO估计与补偿后,残余频偏能压到子载波间隔的1%以内。此时星座图恢复清晰,16QAM在SNR为20dB时BER能降到10^-3量级。这个变化解释了为什么“多普勒补偿”是NTN物理层仿真的核心工作:它直接决定了系统能否正常工作。
我特意对比了三组仿真:
| 仿真条件 | 残余频偏 | SNR=20dB时16QAM BER |
|---|---|---|
| 无同步无补偿 | 300kHz未处理 | 约0.42 |
| 仅小数倍频偏补偿 | 约10kHz | 约0.1 |
| 完整CFO估计+补偿 | <1kHz | 约1e-3 |
这个表说明,小数倍频偏补偿必须和整数倍频偏校正配合使用,缺了任何一环,性能都达不到可用水平。
5.2 不同信道估计与均衡方案的性能对比
信道估计和均衡的组合方式会直接影响性能。我用同一组信道和频偏条件下对比了三种组合:LS+ZF、LS+DFT降噪+MMSE、以及理想信道估计(已知真实信道响应)做下界参考。
| 方案 | SNR=15dB,16QAM BER |
|---|---|
| LS + ZF | 约3e-2 |
| LS + DFT降噪 + MMSE | 约6e-3 |
| 理想信道 + MMSE | 约2e-3 |
可以看出,DFT降噪和MMSE带来的提升非常明显,尤其是把DFT降噪和MMSE搭配使用时,性能已经非常接近理想信道估计的下界。这个结果说明,在NTN这种信道多径少、能量集中的场景下,LS+DFT降噪是个性价比很高的选择。
5.3 一套可以直接运行的仿真参数
为了方便复现,我把仿真中使用的关键参数整理成下表。这套参数在普通双核笔记本上就能跑完,每帧大概10到20秒左右。
| 参数名 | 取值 |
|---|---|
| 载波频率 | 28GHz |
| 子载波间隔 | 120kHz |
| FFT点数 | 2048 |
| 循环前缀长度 | 512采样点 |
| 有效数据子载波 | 1200 |
| 导频间隔 | 每6个子载波插1个 |
| 调制方式 | QPSK / 16QAM |
| LEO轨道高度 | 600km |
| Rician K因子 | 10dB |
| SNR范围 | 0~30dB |
| CFO范围 | 0~500kHz |
| OFDM符号数 | 14个/帧 |
这套参数最大的特点是“接近实际且收敛快”。如果你打算扩展成240kHz子载波间隔,只需要把FFT点数缩小到1024并同步调整CP长度即可,整个链路结构不用做任何修改。
6. 调试中踩过的坑与排查清单
6.1 CFO估计范围不足,导致“怎么也补不回来”
我最初用Moose估计时,直接在整帧训练序列上做相关,D取得很大,结果估计范围只有±60kHz。而仿真里故意加了一个300kHz的大频偏,angle操作在超过±π时发生了相位模糊,估计结果完全错误,星座图照样是乱的。
问题出在D的选择上。Moose算法估计范围是 ±1/(2D·Ts),D越大,范围越小。在120kHz子载波间隔下,FFT为2048时,相应的D·Ts约等于1/120kHz,所以范围为±60kHz。要覆盖300kHz的频偏,D必须缩短到原来的五分之一,但这又会牺牲精度。
正确的做法是先做整数倍频偏校正,再用短D估计小数倍频偏。换句话说,Moose只负责小数部分,大范围的移位交给整数倍频偏校正来完成。这个分工逻辑必须从一开始就定清楚,否则会陷入“频偏估不准导致信道估计失败,信道估计失败又让频偏估计更偏”的恶性循环。
6.2 定时偏差带来的相位斜坡问题
粗定时同步找到的符号起点,和真实起点之间可能存在几个采样点的偏差。这个偏差在时域看似无关紧要,进入频域后会表现为相位斜坡,即每个子载波乘上一个与子载波索引k成正比的相位因子exp(j2πkΔn/N)。
起初我没太在意,结果发现DFT降噪的效果突然变差了。原因就是相位斜坡让信道冲激响应在时域发生了循环移位,本该集中在前面若干径的能量被“平铺”到了整个时域窗内,DFT降噪自然就失效了。
排查方法是在信道估计后观察时域冲激响应的能量分布。如果能量没有集中在前面少量径上,极大概率就是定时偏差没校准。解决办法是做一个细定时搜索,在粗定时附近±几个采样点范围内重新搜索相关峰值,或者用后验的信道冲激响应峰值位置反推定时修正量。
6.3 时变多普勒带来的块内ICI
LEO卫星的多普勒频移是时变的,如果一帧里只用同一个频偏做补偿,即使中心时刻的频率被对准了,帧头和帧尾也会残留一定数量的残余频偏。残余频偏在高SNR下体现为星座点旋转加发散,严重限制误码性能。
解决思路是分块补偿,把一帧分成几个子块,每个子块单独估计频偏并补偿。块长度越短,多普勒变化跟踪得越准,但块太短会导致频偏估计用的训练数据不足,方差变大。我实测下来,一个块包含7个OFDM符号已经能较好地平衡跟踪速度和估计精度。
另外,如果场景中的多普勒变化率特别快,还建议在时域把相位轨迹建模成一阶或二阶多项式,然后用最小二乘拟合整体补偿,这种“多项式相位补偿”在LEO场景下效果更平滑,不会出现块与块之间的相位跳变。
6.4 仿真里最容易出现的“自我欺骗”
调试NTN链路时,我容易犯一个隐蔽的错误:频偏补偿前已经知道了真实的频偏值,于是直接把频偏“减去”,而不是先用估计算法估出来再补偿。这样得到的结果当然很漂亮,但完全没有验证估计器的能力。一旦后面换成更恶劣的信道或更低的SNR,算法性能就会现出原形。
所以我在仿真结构里做了严格分离:发射端用一个真实的时变多普勒生成函数去污染信号,接收端只用被污染后的信号做频偏估计,估计器的输出再用于补偿。整个过程中,真实频偏值只用于性能对比和误差统计,绝不参与补偿。这样才能真实地评估算法的鲁棒性。
另外还要提醒一点,噪声和随机种子要统一管理。每次跑同一个配置时,随机种子不同会导致BER曲线有几倍的抖动。我的做法是在仿真开头固定随机种子,同一组参数至少重复跑20帧求平均,这样得到的BER曲线才平滑,也有可复现性。
6.5 做NTN仿真的一些心得体会
这个项目做到后面,我最大的体会是:面向6G的星地融合NTN链路,最难的不是某个单独的算法,而是把卫星运动、多普勒、同步、信道估计这些模块串成一个能稳定运转的整体。每一个模块单独拿出来都不算复杂,但一旦把它们放在LEO这种大动态环境里,模块之间的耦合会变得非常强——频偏估计不准,信道估计就很难做好;信道估计做不好,均衡性能就上不去;均衡上不去,误码率就飙升。调试的时候需要有全局视角,不能只看某一级的输出。
如果你也想搭一套NTN仿真,我的建议是先在最简单的配置下把链路跑通:QPSK调制、无多普勒、无频偏,确认发射接收链路无误码。然后逐步加入信道衰落、加性噪声、整数倍和小数倍频偏,每一步都观察星座图和BER的变化。等每个模块都单独验证过,再把LEO时变多普勒和CFO联合起来做整体测试。这样一层层加复杂度,出问题时定位范围很小,排查效率比直接跑完整系统高得多。
最后把调试排查的要点整理成一个清单,方便对照:
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 星座图环形旋转 | 小数倍CFO未补偿干净 | 检查Moose估计输出与真实频偏的误差 |
| 星座图整体错位 | 整数倍频偏没有校正 | 检查频域导频互相关峰值位置 |
| 高频子载波BER很差 | 定时偏差导致相位斜坡 | 观察时域信道冲激响应是否集中 |
| 帧尾部星座图发散 | 时变多普勒未分块补偿 | 检查不同OFDM符号的残余频偏 |
| 高SNR下BER仍不收敛 | 噪声方差估计不准 | 检查MMSE均衡中的σ²是否合理 |
这套链路仿真做完之后,我对卫星信道物理层处理的理解上了一个台阶。如果后续再做扩展,我大概率会往两个方向走:一是把MIMO和波束成形加进来,看看星地链路在空间维度上的增益;二是把波形换成OTFS或者带保护的DFT-s-OFDM,对比不同波形在LEO高多普勒场景下的表现。这些方向都可以基于现有链路做增量开发,模块化的结构让替换起来并不困难。