看文獻過程中不斷發現有太多不懂的基礎知識,故長期更新這類blog不斷補充在這過程中學到的知識。由于這些內容與我的研究方向并不一定強相關,故記錄不會很深入請見諒。
【通信基礎知識補充10】25年9月通信基礎知識補充1:NTN-TDL信道建模matlab代碼(satellite-communications toolbox學習)
- 一、設置NTN信道參數 (Set NTN Channel Common Parameters)
- 二、NTN 窄帶信道 (NTN Narrowband Channel)
- 三、NTN TDL 信道
matlab satellite-communications toolbox 代碼地址
一、設置NTN信道參數 (Set NTN Channel Common Parameters)
?? 設置用于建模非地面網絡(NTN)窄帶平坦衰落信道和 NTN 時域延遲(TDL)信道所需的通用參數。此示例對一顆在 600 千米高度運行的低地球軌道(LEO)衛星進行建模,其工作頻段為 S 波段。假設移動設備或用戶設備(UE)的速度為 3 千米/小時。這些默認參數來自 3GPP TR 38.821 表 6.1.2-4。
%% 1. Set NTN Channel Common Parameters
% ------------ 1.1 設置常規參數 ------------
commonParams = struct;
commonParams.CarrierFrequency = 2e9; % 載波頻率,單位 Hz(2 GHz)
commonParams.ElevationAngle = 50; % 衛星仰角,單位度
commonParams.SatelliteAltitude = 600000; % 衛星高度,單位米(600 km)
commonParams.MobileAltitude = 0; % 移動設備高度,單位米(地面水平)
commonParams.MobileSpeed = 3*1000/3600; % 移動設備速度,單位 m/s(3 km/h 轉換為 m/s)
commonParams.SampleRate = 7680000; % 采樣率,單位 Hz(8 MHz)
commonParams.RandomStream = "mt19937ar with seed"; % 隨機流設置,用于保證結果的可復現性% 選擇項:% "mt19937ar with seed":Mersenne Twister 算法(設定種子保證可復現性)% "Global stream":使用全局隨機流(適用于不需要控制隨機性時)commonParams.Seed = 73; % 隨機種子,用于初始化隨機數生成器
commonParams.NumSinusoids = 48; % 用于多普勒擴展建模的正弦波數量% ------------ 1.2 計算衛星多普勒頻移 ------------
% 使用衛星和用戶的相對運動來計算衛星的多普勒頻移
satelliteDopplerShift = dopplerShiftCircularOrbit( ...commonParams.ElevationAngle, ...commonParams.SatelliteAltitude, ...commonParams.MobileAltitude, ...commonParams.CarrierFrequency);% 計算由于移動設備的運動產生的最大多普勒頻移
c = physconst('lightspeed'); % 光速
mobileMaxDoppler = commonParams.MobileSpeed * commonParams.CarrierFrequency / c;
衛星多普勒頻移的計算函數如下:
function shift = dopplerShiftCircularOrbit(el,hs,hg,freq,time)
%dopplerShiftCircularOrbit Doppler shift due to satellite movement in circular orbit
% Copyright 2023-2024 The MathWorks, Inc.
%#codegen% 參數驗證塊(確保輸入參數合法)arguments% 仰角(必須為實數/有限值/非空)el (1,:) {mustBeA(el,{'double','single'}), mustBeReal, mustBeFinite, mustBeNonempty}% 衛星高度(必須為正實數)hs (1,1) {mustBeA(hs,{'double','single'}), mustBeReal, mustBeFinite, mustBeNonempty, mustBePositive}% 地面站高度(必須非負且小于衛星高度)hg (1,1) {mustBeA(hg,{'double','single'}), mustBeReal, mustBeFinite, mustBeNonempty, mustBeNonnegative, mustBeLessThan(hg,hs)}% 載波頻率(必須為實數)freq (1,1) {mustBeA(freq,{'double','single'}), mustBeReal, mustBeFinite, mustBeNonempty} % 時間序列(可選,默認0)time (1,:) {mustBeA(time,{'double','single'}), mustBeReal, mustBeFinite, mustBeNonempty} = 0end% 獲取圓形軌道的多普勒統計信息% 內部調用 circularOrbitStats 計算軌道動力學參數info = satcom.internal.circularOrbitStats(el, hs, hg, time, freq);% 提取多普勒頻移結果shift = info.DopplerShift;
end
二、NTN 窄帶信道 (NTN Narrowband Channel)
?? 如 3GPP TR 38.811 第 6.7.1 節所定義,該代碼支持 NTN 平坦衰落窄帶信道所有可用的陸地移動衛星 (LMS) 場景。S波段定義的 LMS 場景包括:城市 (Urban)、郊區 (Suburban)、鄉村林地 (RuralWooded) 、住宅區 (Residential)。Ka 波段定義的 LMS 場景包括:郊區 (Suburban)、鄉村林地 (RuralWooded)。下面是各場景的典型特征:
場景 (Scenario) | 環境描述與特點 | 對信道的影響 |
---|---|---|
城市 (Urban) | 密集的高層建筑、街道峽谷。 | 最惡劣的場景。直射路徑(LOS)被嚴重遮擋甚至完全阻擋(NLOS為主),信號經歷嚴重的陰影衰落和豐富的多徑反射,導致深衰落和信號波動劇烈。 |
郊區 (Suburban) | 低層建筑、住宅區、更開闊的道路,有一些樹木。 | 環境介于城市和鄉村之間。存在LOS的概率比城市高,但也會經歷一定程度的遮擋和多徑效應。信道條件優于城市,但劣于鄉村。 |
鄉村林地 (RuralWooded) | 開闊地、農田,但存在成片的樹林或小森林。 | 主要遮擋物是樹木。樹林會部分遮擋或散射信號,導致信號強度發生中等到顯著的變化。LOS條件比郊區更常見,但可能因樹葉密度而季節性地變化。 |
住宅區 (Residential) | 獨立的房屋、低密度住宅區,有花園和零星的樹木。 | 與郊區類似,但建筑密度更低,環境更開闊。直射路徑通常較好,多徑分量相對較弱且主要來自房屋和地面的反射。信道條件通常較好。 |
S波段 vs Ka波段 | S波段(2-4 GHz)頻率較低,Ka波段(26.5-40 GHz)頻率非常高。 | Ka波段信號波長短,更容易被小雨滴、樹葉等小物體吸收和散射,因此雨衰和植被衰減比S波段嚴重得多。這意味著即使在相同名稱的場景(如Suburban)下,Ka波段的信道條件也會比S波段更差。 |
?? 總結:選擇不同的LMS場景,實質上是在選擇不同環境遮擋程度和載波頻率的組合。Urban代表最嚴重的遮擋和衰落,Residential代表較好的條件。而相同名稱的場景在Ka波段下會比在S波段下更具挑戰性。在仿真中,這些差異會通過不同的統計模型參數來實現,從而影響最終的鏈路性能和系統設計選擇(如所需的鏈路余量)。
?? 以下代碼為 NTN 窄帶信道配置了一個城市 (Urban) LMS 場景,步驟如下:
?? 1.設置特定于 NTN 平坦衰落窄帶信道的信道參數。
?? 2.生成 NTN 平坦衰落窄帶信道。
?? 3.可視化衰落或濾波后信號的頻譜。
%% 2. NTN Narrowband Channel
% ------------ 初始化 NTN 平坦衰落窄帶信道 ------------
% 使用 p681LMSChannel 初始化 NTN 信道模型
ntnNarrowbandChan = p681LMSChannel;
ntnNarrowbandChan.SampleRate = commonParams.SampleRate;
ntnNarrowbandChan.CarrierFrequency = commonParams.CarrierFrequency;
ntnNarrowbandChan.ElevationAngle = commonParams.ElevationAngle;
ntnNarrowbandChan.MobileSpeed = commonParams.MobileSpeed;
ntnNarrowbandChan.SatelliteDopplerShift = satelliteDopplerShift;
ntnNarrowbandChan.RandomStream = commonParams.RandomStream; % 設置隨機數流為 "mt19937ar with seed"
ntnNarrowbandChan.Seed = commonParams.Seed;
ntnNarrowbandChan.Environment = "Urban"; % 環境模型選擇:"Urban", "Suburban", "Rural", "Custom"% 可選:% "Urban":城市環境模型,建筑物的反射、多徑衰落影響% "Suburban":郊區環境模型,適用于中等密度地區% "Rural":鄉村環境,遠離城市的自然環境% "Custom":自定義環境設置,可手動定義路徑損失、多徑等ntnNarrowbandChan.AzimuthOrientation = 0; % 方位角朝向為0度,表示移動終端的運動方向與衛星方位完全一致
ntnNarrowbandChan.FadingTechnique = "Sum of sinusoids"; % 衰落模型選擇: "Sum of sinusoids" 或 "Filtered Gaussian noise"% "Sum of sinusoids":正弦波疊加模型,模擬平坦衰落% "Filtered Gaussian noise":濾波高斯噪聲模型,適用于復雜衰落ntnNarrowbandChan.NumSinusoids = commonParams.NumSinusoids;% 如果選擇"Custom"則需要自定義環境,則需要進一步設置環境參數
if strcmpi(ntnNarrowbandChan.Environment,'Custom')% 定義自定義環境中的路徑損失、多徑功率系數等ntnNarrowbandChan.StateDistribution = [3.0639 2.9108; 1.6980 1.2602];ntnNarrowbandChan.MinStateDuration = [10 6];ntnNarrowbandChan.DirectPathDistribution = [-1.8225 -15.4844; 1.1317 3.3245];ntnNarrowbandChan.MultipathPowerCoefficients = [-0.0481 0.9434; -14.7450 -1.7555];ntnNarrowbandChan.StandardDeviationCoefficients = [-0.4643 -0.0798; 0.3334 2.8101];ntnNarrowbandChan.DirectPathCorrelationDistance = [1.7910 1.7910];ntnNarrowbandChan.TransitionLengthCoefficients = [0.0744; 2.1423];ntnNarrowbandChan.StateProbabilityRange = [0.05 0.1; 0.95 0.9];
end% 獲取 p681 LMS 基帶信道模型的信息,并檢查信道濾波延遲為0(由于平坦衰落)
p681ChannelInfo = info(ntnNarrowbandChan);
% ------------ 生成 NTN 平坦衰落窄帶信道 ------------
% 生成一個隨機輸入信號
rng(commonParams.Seed);
in = randn(commonParams.SampleRate, 1, 'like', 1i); % 生成復數高斯信號
% 通過 NTN 信道對輸入信號進行濾波,得到路徑增益和輸出
[narrowbandOut, narrowbandPathGains, narrowbandSampleTimes] = ntnNarrowbandChan(in);% 可視化接收信號的頻譜
% ntnNarrowbandAnalyzer = spectrumAnalyzer('SampleRate', ntnNarrowbandChan.SampleRate);
% ntnNarrowbandAnalyzer.Title = "Received Signal Spectrum " + "NTN Narrowband with " + string(ntnNarrowbandChan.Environment) + " environment";
% ntnNarrowbandAnalyzer.ShowLegend = true;
% ntnNarrowbandAnalyzer.ChannelNames = "Rx Antenna 1";
% ntnNarrowbandAnalyzer(narrowbandOut);
三、NTN TDL 信道
?? 該代碼支持 3GPP TR 38.811 第 6.9.2 節中定義的所有四種 NTN TDL 信道配置文件。這四種信道配置文件分別為:NTN-TDL-A、NTN-TDL-B、NTN-TDL-C、NTN-TDL-D,具體如下表所示:
?? 關鍵特性說明:
?? 1.NTN-TDL-A 和 NTN-TDL-B 信道配置文件定義為非視距(NLOS) 條件。
?? 2.NTN-TDL-C 和 NTN-TDL-D 信道配置文件定義為視距(LOS) 條件。
?? 3.所有四種信道配置文件均在50度仰角下定義(可以認為是比較理想的情況)。
?? 補充:NTN TDL 信道與地面 TDL 信道的主要區別:
?? 1.多普勒頻移補償:NTN TDL 信道除了考慮移動終端或用戶設備(UE)運動引起的多普勒頻移外,還考慮了衛星運動引起的多普勒頻移。
?? 2.延遲特性差異:由于大傳播延遲(單程傳播時延為ms級)和不同的散射環境(由于衛星離地很遠,這些反射路徑與直射路徑的夾角非常小),NTN TDL 信道的延遲配置文件與地面 TDL 信道配置文件不同。
?? 按照 3GPP TR 38.811 第 6.9.2 節 [1] 的規定,對 NTN 頻率選擇性衰落 TDL 信道進行建模步驟如下:
?? 1.設置特定于 NTN 頻率選擇性衰落 TDL 信道的參數
?? 2.生成 NTN 頻率選擇性衰落 TDL 信道
?? 3.可視化衰落或濾波后信號的頻譜
%% 3. NTN TDL Channel
% ------------ 初始化 NTN TDL 信道 ------------
% 使用 nrTDLChannel 設置 NTN-TDL 信道(選擇 DelayProfile)
ntnTDLChan = nrTDLChannel;
ntnTDLChan.DelayProfile = "NTN-TDL-D"; % 選擇 NTN-TDL-C 配置% 可選:% "NTN-TDL-A":適用于視距(LOS)環境的延遲配置% "NTN-TDL-B":適用于視距(LOS)環境的不同配置% "NTN-TDL-C":適用于視距(LOS)環境的另一種延遲配置(常用于衛星通信)% "NTN-TDL-D":適用于非視距(NLOS)環境的配置% "Custom":自定義延遲配置,手動設置多徑和延遲ntnTDLChan.DelaySpread = 30e-9; % 設置延遲擴展(30 ns)
ntnTDLChan.TransmissionDirection = "Downlink"; % 下行鏈路
ntnTDLChan.MIMOCorrelation = "Low"; % MIMO 相關性設置為低% 可選:% "Low":低相關性,天線間信號獨立性強% "Medium":中等相關性,適合密集環境% "High":高相關性,適合非常密集的環境% "Custom":自定義MIMO相關性矩陣ntnTDLChan.Polarization = "Co-Polar"; % 極化方式% 可選:% "Co-Polar":同極化,發送和接收天線使用相同的極化方式% "Cross-Polar":交叉極化,發送和接收天線使用相對垂直的極化方式% "Custom":自定義極化設置ntnTDLChan.SampleRate = commonParams.SampleRate;
ntnTDLChan.MaximumDopplerShift = mobileMaxDoppler; % 設置最大多普勒頻移
ntnTDLChan.SatelliteDopplerShift = satelliteDopplerShift; % 衛星的多普勒頻移
ntnTDLChan.RandomStream = commonParams.RandomStream;
ntnTDLChan.Seed = commonParams.Seed;% ------------ 設置天線配置 ------------
if ~strcmpi(ntnTDLChan.MIMOCorrelation,'Custom')ntnTDLChan.NumTransmitAntennas = 1; % 發送天線數ntnTDLChan.NumReceiveAntennas = 2; % 接收天線數
else% 自定義 MIMO 相關性配置if any(strcmpi(ntnTDLChan.Polarization,{'Co-Polar','Cross-Polar'}))ntnTDLChan.TransmitCorrelationMatrix = 1;ntnTDLChan.ReceiveCorrelationMatrix = [1 0; 0 1];end% 自定義交叉極化設置if strcmpi(ntnTDLChan.Polarization,'Cross-Polar')ntnTDLChan.TransmitPolarizationAngles = [45 -45]; % 發送極化角度ntnTDLChan.ReceivePolarizationAngles = [90 0]; % 接收極化角度ntnTDLChan.XPR = 10; % 極化交叉比,單位 dBendif strcmpi(ntnTDLChan.Polarization,'Custom')ntnTDLChan.SpatialCorrelationMatrix = [1 0; 0 1]; % 空間相關矩陣end
end% ------------ 生成 NTN TDL 信道的隨機輸入信號 ------------
% 生成一個隨機輸入信號
rng(commonParams.Seed);
in = randn(commonParams.SampleRate, ntnTDLChan.NumTransmitAntennas, 'like', 1i);% 通過 NTN-TDL 信道生成衰落波形
[tdlOut, tdlPathGains, tdlSampleTimes] = ntnTDLChan(in);% ------------ 可視化 NTN TDL 信道的接收信號頻譜 ------------
% 可視化 NTN TDL 信道的頻譜
ntnTDLAnalyzer = spectrumAnalyzer('SampleRate', ntnTDLChan.SampleRate);
ntnTDLAnalyzer.Title = "Received Signal Spectrum " + "NTN TDL with " + string(ntnTDLChan.DelayProfile) + " delay profile";
ntnTDLAnalyzer.ShowLegend = true;for nRx = 1:size(tdlOut,2)ntnTDLAnalyzer.ChannelNames{nRx} = "Rx Antenna " + nRx;
end
ntnTDLAnalyzer(tdlOut); % 顯示接收信號的頻譜
?? 上述代碼都是封裝好的,修改起來沒那么絲滑,若想進一步修改函數定義,同時學習TDL信道是如何設定的,則需要找到函數nrTDLChannel.m進一步學習。例如,以下為根據指定的延遲配置文件(自定義或預定義)生成TDL信道的路徑延遲和增益的代碼,特別處理了LOS路徑的拆分與合并,最終輸出合并后的路徑延遲、增益以及第一抽頭的K因子。
函數使用范例如下所示:
% 示例 1:
% 配置TDL信道,對輸入信號進行濾波,并繪制接收波形頻譜。
% 使用TDL-C延遲配置文件,300 ns時延擴展和UE速度30 km/h。
%
% v = 30.0; % UE速度,單位km/h
% fc = 4e9; % 載波頻率,單位Hz
% c = physconst('lightspeed'); % 光速,單位m/s
% fd = (v*1000/3600)/c*fc; % UE最大多普勒頻移,單位Hz
%
% tdl = nrTDLChannel;
% tdl.DelayProfile = 'TDL-C';
% tdl.DelaySpread = 300e-9;
% tdl.MaximumDopplerShift = fd;
%
% % 創建1個子幀時長的隨機波形(1天線),通過信道并繪制接收波形頻譜
%
% SR = 30.72e6;
% T = SR * 1e-3;
% tdl.SampleRate = SR;
% tdlinfo = info(tdl);
% Nt = tdlinfo.NumTransmitAntennas;
%
% txWaveform = complex(randn(T,Nt),randn(T,Nt));
%
% rxWaveform = tdl(txWaveform);
%
% analyzer = spectrumAnalyzer('SampleRate',tdl.SampleRate);
% analyzer.Title = ['接收信號頻譜 ' tdl.DelayProfile];
% analyzer(rxWaveform);
%
% % 示例 2:
% % 繪制SISO情況下TDL-E延遲配置文件的路徑增益,多普勒頻移為70 Hz。
%
% tdl = nrTDLChannel;
% tdl.SampleRate = 500e3;
% tdl.NumTransmitAntennas = 1;
% tdl.NumReceiveAntennas = 1;
% tdl.MaximumDopplerShift = 70;
% tdl.DelayProfile = 'TDL-E';
%
% % 虛擬輸入信號,其長度決定生成的路徑增益樣本數
% in = zeros(1000,tdl.NumTransmitAntennas);
%
% % 生成路徑增益
% [~, pathGains] = tdl(in);
% mesh(10*log10(abs(pathGains)));
% view(26,17); xlabel('信道路徑');
% ylabel('樣本(時間)'); zlabel('幅度(dB)');
%
% % 示例 3:
% % 配置交叉極化天線的信道并濾波輸入信號。
% % 使用TDL-D延遲配置文件,10 ns時延擴展和期望總體K因子7.0 dB。
% % 根據TS 36.101附錄B.2.3A.3 4x2高相關配置交叉極化天線。
%
% tdl = nrTDLChannel;
% tdl.NumTransmitAntennas = 4;
% tdl.DelayProfile = 'TDL-D';
% tdl.DelaySpread = 10e-9;
% tdl.KFactorScaling = true;
% tdl.KFactor = 7.0; % 期望模型K因子(K_desired),單位dB
% tdl.MIMOCorrelation = 'High';
% tdl.Polarization = 'Cross-Polar';
%
% % 創建4天線1個子幀時長的隨機波形,通過信道
%
% SR = 1.92e6;
% T = SR * 1e-3;
% tdl.SampleRate = SR;
% tdlinfo = info(tdl);
% Nt = tdlinfo.NumTransmitAntennas;
%
% txWaveform = complex(randn(T,Nt),randn(T,Nt));
%
% rxWaveform = tdl(txWaveform);
%
% % 示例 4:
% % 配置自定義延遲配置文件的信道并濾波輸入信號。
% % 設置兩個信道抽頭如下:
% % 抽頭1:萊斯,平均功率0 dB,K因子10 dB,延遲零
% % 抽頭2:瑞利,平均功率-5 dB,延遲45 ns
%
% tdl = nrTDLChannel;
% tdl.NumTransmitAntennas = 1;
% tdl.DelayProfile = 'Custom';
% tdl.FadingDistribution = 'Rician';
% tdl.KFactorFirstTap = 10.0; % 第一抽頭K因子(K_1),單位dB
% tdl.PathDelays = [0.0 45e-9];
% tdl.AveragePathGains = [0.0 -5.0];
%
% % 創建1天線1個子幀時長的隨機波形,通過信道
%
% SR = 30.72e6;
% T = SR * 1e-3;
% tdl.SampleRate = SR;
% tdlinfo = info(tdl);
% Nt = tdlinfo.NumTransmitAntennas;
%
% txWaveform = complex(randn(T,Nt),randn(T,Nt));
%
% rxWaveform = tdl(txWaveform);
%
% % 示例 5:
% % 為高度600 km、速度7562.2 m/s、與UE仰角50度的衛星配置NTN信道。
% % 使用NTN-TDL-A配置文件,100 ns時延擴展,UE速度3 km/h,載波頻率2 GHz。
%
% % 計算衛星運動引起的多普勒頻移和UE周圍散射環境引起的最大多普勒頻移
% r = physconst('earthradius'); % 地球半徑,單位m
% c = physconst('lightspeed'); % 光速,單位m/s
% fc = 2e9; % 載波頻率,單位Hz
% theta = 50; % 仰角,單位度
% h = 600e3; % 衛星高度,單位m
% vSat = 7562.2; % 衛星速度,單位m/s
% vUE = 3 * 1000/3600; % UE速度,單位m/s
% fdMaxUE = (vUE*fc)/c; % UE最大多普勒頻移,單位Hz
% fdSat = (vSat*fc/c)*(r*cosd(theta)/(r+h)); % 衛星多普勒頻移,單位Hz
%
% % 配置TDL信道
% ntnChan = nrTDLChannel;
% ntnChan.DelayProfile = 'NTN-TDL-A';
% ntnChan.DelaySpread = 100e-9;
% ntnChan.SatelliteDopplerShift = fdSat;
% ntnChan.MaximumDopplerShift = fdMaxUE;
%
% % 使用配置的天線數創建1個子幀時長的隨機波形
% SR = 30.72e6;
% T = SR*1e-3;
% ntnChan.SampleRate = SR;
% ntnChanInfo = info(ntnChan);
% Nt = ntnChanInfo.NumTransmitAntennas;
% txWaveform = randn(T,Nt,'like',1i);
%
% % 使波形通過信道
% rxWaveform = ntnChan(txWaveform);
%
% 另見 nrCDLChannel, nrHSTChannel, comm.MIMOChannel,
% nrPerfectTimingEstimate, nrPerfectChannelEstimate.% 版權所有 2016-2024 The MathWorks, Inc.%#codegen% =========================================================================
% 公共接口
該函數的代碼如下:
function [pathDelaysOut, pathGainsOut, K_1dB] = getDelayProfile(obj)% getDelayProfile - 獲取TDL信道的延遲分布特性% 該函數根據指定的延遲配置文件生成路徑延遲和路徑增益%% 輸入參數:% obj - nrTDLChannel對象實例%% 輸出參數:% pathDelaysOut - 輸出的路徑延遲向量(單位:秒)% pathGainsOut - 輸出的路徑增益向量(單位:dB)% K_1dB - 第一抽頭的萊斯K因子(單位:dB),若無LOS路徑則為-Inf% 聲明外部函數(這些函數在代碼生成時需要特殊處理)coder.extrinsic('nr5g.internal.nrTDLChannel.getTDLProfile');coder.extrinsic('wireless.internal.channelmodels.scaleDelaysAndKFactor');%% 處理自定義延遲配置文件if strcmpi(obj.DelayProfile, 'Custom')% 使用用戶自定義的路徑延遲和增益pathDelaysIn = obj.PathDelays;pathGainsIn = obj.AveragePathGains;% 檢查是否存在LOS路徑if nrTDLChannel.hasLOSPath(obj)% 存在LOS路徑時,將第一抽頭拆分為LOS部分和Rayleigh部分% 根據K_1因子進行拆分% 獲取第一抽頭的K因子(dB)并轉換為線性值K_1dB = obj.KFactorFirstTap;K_1 = 10^(K_1dB/10);% 獲取第一抽頭的總功率(dB)并轉換為線性值P_1dB = pathGainsIn(1);P_1 = 10^(P_1dB/10);% 拆分第一抽頭:% LOS部分功率 = P_1 * K_1 / (1 + K_1)% Rayleigh部分功率 = P_1 / (1 + K_1)losPower = P_1 * K_1 / (1 + K_1);rayleighPower = P_1 / (1 + K_1);% 創建新的延遲向量:% 將原第一抽頭的延遲拆分為兩個相同的延遲值pathDelays = [pathDelaysIn(1), pathDelaysIn(1), pathDelaysIn(2:end)];% 創建新的增益向量:% 將原第一抽頭的增益拆分為LOS和Rayleigh兩部分pathGains = [10*log10(losPower), ... % LOS部分增益(dB)10*log10(rayleighPower), ... % Rayleigh部分增益(dB)pathGainsIn(2:end)]; % 其余抽頭增益else% 無LOS路徑時,直接使用自定義參數pathDelays = pathDelaysIn;pathGains = pathGainsIn;end%% 處理預定義延遲配置文件else% 初始化期望的K因子desiredKFactor = NaN;% 檢查是否存在LOS路徑if nrTDLChannel.hasLOSPath(obj)% 如果啟用了K因子縮放,則使用指定的K因子if obj.KFactorScalingdesiredKFactor = obj.KFactor;endend% 獲取預定義的延遲分布(PDP)pdp = coder.const(double(nr5g.internal.nrTDLChannel.getTDLProfile(obj.DelayProfile)));% 對非簡化延遲配置文件執行延遲和K因子縮放% 簡化配置文件列表(不進行縮放)simplifiedProfiles = {'TDLA30','TDLB100','TDLC300','TDLC60','TDLD30',...'TDLA10','TDLD10','NTN-TDLA100','NTN-TDLC5'};if ~any(strcmp(obj.DelayProfile, simplifiedProfiles))% 對延遲和K因子進行縮放pdp = coder.const(double(wireless.internal.channelmodels.scaleDelaysAndKFactor(...pdp, desiredKFactor, obj.DelaySpread)));end% 從PDP中提取路徑延遲(第1列)和路徑增益(第2列)pathDelays = pdp(:,1).'; pathGains = pdp(:,2).'; end%% 合并LOS和Rayleigh部分(如果存在)% 無論使用自定義還是預定義配置,如果存在LOS路徑,% 此時第一抽頭已被拆分為LOS和Rayleigh兩部分if nrTDLChannel.hasLOSPath(obj)% 計算K因子: LOS增益 - Rayleigh增益K_1dB = pathGains(1) - pathGains(2);% 合并LOS和Rayleigh部分的功率:% 先將兩部分功率轉換為線性值,相加后再轉換回dBtotalPower = 10^(pathGains(1)/10) + 10^(pathGains(2)/10);pathGainsOut = [10*log10(totalPower), pathGains(3:end)];% 更新延遲向量: 移除Rayleigh部分對應的延遲pathDelaysOut = pathDelays([1, 3:end]);else% 無LOS路徑時,K因子設為-InfK_1dB = -Inf;% 直接使用原始增益和延遲pathGainsOut = pathGains;pathDelaysOut = pathDelays;end
end
函數doppler.m則為關于多普勒頻移的模擬:
function s = doppler(specType, varargin)
%DOPPLER 構造多普勒頻譜結構體,用于衰落信道系統對象
% 該函數創建特定類型的多普勒頻譜結構體,用于衰落信道建模
%
% s = doppler(SPECTYPE) 構造指定SPECTYPE類型的多普勒頻譜結構體
% 返回的結構體s包含SpectrumType字段,部分類型還包含其他依賴字段
%
% 支持的頻譜類型及其依賴字段和默認值:
% -----------------------------------------------------------------------
% 頻譜類型 | 依賴字段 | 默認值
% -----------------------|----------------------------|-----------------
% 'Jakes' | 無 | 無
% 'Flat' | 無 | 無
% 'Rounded' | Polynomial(多項式系數) | [1 -1.72 0.785]
% 'Bell' | Coefficient(系數) | 9
% 'Asymmetric Jakes' | NormalizedFrequencyInterval(歸一化頻率區間) | [0 1]
% 'Restricted Jakes' | NormalizedFrequencyInterval(歸一化頻率區間) | [0 1]
% 'Gaussian' | NormalizedStandardDeviation(歸一化標準差) | 1/sqrt(2)
% 'BiGaussian' | NormalizedStandardDeviations(歸一化標準差) | 1/sqrt(2)*[1 1]
% | NormalizedCenterFrequencies(歸一化中心頻率) | [0 0]
% | PowerGains(功率增益) | [0.5 0.5]
% -----------------------------------------------------------------------
%
% 函數也支持通過輸入參數指定依賴字段的值。以下是各頻譜類型的詳細說明和解析表達式,
% 其中fd表示關聯衰落信道系統對象的MaximumDopplerShift(最大多普勒頻移)
%
% s = doppler('Jakes') 構造Jakes多普勒頻譜結構體
% 理論Jakes多普勒頻譜解析表達式:
% S(f) = 1/(pi*fd*sqrt(1-(f/fd)^2)) -fd <= f <= fd
%
% s = doppler('Flat') 構造平坦多普勒頻譜結構體
% 理論平坦多普勒頻譜解析表達式:
% S(f) = 1/(2*fd) -fd <= f <= fd
%
% s = doppler('Rounded', POLY) 構造圓潤多普勒頻譜結構體
% 參數POLY設置Polynomial字段,理論表達式為4階多項式(僅含偶次項):
% S(f) = a0 + a2*(f/fd)^2 + a4*(f/fd)^4 -fd <= f <= fd
% 系數a0, a2, a4通過POLY = [a0 a2 a4]指定
%
% s = doppler('Bell', COEFF) 構造鐘形多普勒頻譜結構體
% 參數COEFF設置Coefficient字段,理論表達式:
% S(f) = 1/(1 + c*(f/fd)^2) -fd <= f <= fd
% 其中c = COEFF為非負實數標量
%
% s = doppler('Asymmetric Jakes', FREQINTERVAL) 構造非對稱Jakes頻譜
% 參數FREQINTERVAL設置NormalizedFrequencyInterval字段,理論表達式:
% S(f) = 1/(pi*fd*sqrt(1-(f/fd)^2)) fmin <= f <= fmax
% 其中fmin和fmax通過FREQINTERVAL = [fmin/fd fmax/fd]指定(歸一化值)
%
% s = doppler('Restricted Jakes', FREQINTERVAL) 構造受限Jakes頻譜
% 參數FREQINTERVAL設置NormalizedFrequencyInterval字段,理論表達式:
% S(f) = 1/(pi*fd*sqrt(1-(f/fd)^2)) fmin <= |f| <= fmax
% 其中fmin和fmax通過FREQINTERVAL = [fmin/fd fmax/fd]指定(歸一化值)
%
% s = doppler('Gaussian', STDDEVIATION) 構造高斯多普勒頻譜
% 參數STDDEVIATION設置NormalizedStandardDeviation字段,理論表達式:
% S(f) = 1/sqrt(2*pi*stdDev^2) * exp(-f^2/(2*stdDev^2))
% 其中stdDev通過STDDEVIATION = stdDev/fd指定(歸一化標準差)
%
% s = doppler('BiGaussian', 'NormalizedStandardDeviations', STDDEVIATION,
% 'NormalizedCenterFrequencies', CENTERFREQ,
% 'PowerGains', GAIN) 構造雙高斯多普勒頻譜
% 參數說明:
% STDDEVIATION = [stdDev1/fd stdDev2/fd] (歸一化標準差)
% CENTERFREQ = [fc1/fd fc2/fd] (歸一化中心頻率)
% GAIN = [gain1 gain2] (功率增益分量)
% 理論表達式:
% S(f) = gain1/sqrt(2*pi*stdDev1^2)*exp(-(f-fc1)^2/(2*stdDev1^2))
% + gain2/sqrt(2*pi*stdDev2^2)*exp(-(f-fc2)^2/(2*stdDev2^2))
%
% 示例:
% % 構造Jakes多普勒頻譜
% doppler('Jakes')
%
% % 構造自定義多項式系數的圓潤多普勒頻譜
% doppler('Rounded', [1 2 1])
%
% % 構造系數為3的鐘形多普勒頻譜
% doppler('Bell', 3)
%
% % 構造受限Jakes頻譜(歸一化頻率區間[0, 0.5])
% doppler('Restricted Jakes', [0 0.5])
%
% % 構造雙高斯頻譜(自定義中心頻率)
% doppler('BiGaussian', 'NormalizedCenterFrequencies', [0.1 0.8])
%
% 另見:comm.RayleighChannel, comm.RicianChannel, comm.MIMOChannel% 版權所有 2012-2018 The MathWorks, Inc.% 確保specType為字符類型
specType = convertStringsToChars(specType);
coder.internal.errorIf(~ischar(specType), 'comm:doppler:InvalidSpecType');%% 根據頻譜類型處理不同情況
switch specTypecase {'Jakes', 'Flat'} % Jakes和平坦頻譜narginchk(1, 1); % 驗證輸入參數數量s = struct('SpectrumType', specType); % 創建基礎結構體case 'Bell' % 鐘形頻譜narginchk(1, 2); % 驗證輸入參數數量if nargin == 2% 驗證系數參數有效性validateattributes(varargin{1}, {'numeric'}, ...{'real','scalar','nonnegative','finite'}, ...'doppler(''Bell'', Coefficient)', 'Coefficient');coeff = varargin{1};elsecoeff = 9; % 默認系數end% 創建包含系數的結構體s = struct('SpectrumType', specType, ...'Coefficient', coeff);case 'Rounded' % 圓潤頻譜narginchk(1, 2); % 驗證輸入參數數量if nargin == 2% 驗證多項式參數有效性validateattributes(varargin{1}, {'numeric'}, ...{'real','row','ncols',3,'finite'}, ...'doppler(''Rounded'', Polynomial)', 'Polynomial');poly = varargin{1};elsepoly = [1 -1.7200 0.7850]; % 默認多項式系數end% 創建包含多項式的結構體s = struct('SpectrumType', specType, ...'Polynomial', poly);case {'Asymmetric Jakes', 'Restricted Jakes'} % 非對稱/受限Jakes頻譜narginchk(1, 2); % 驗證輸入參數數量if nargin == 2% 確定頻率區間的最小邊界minBound = strcmp(specType, 'Restricted Jakes') - 1;% 驗證頻率區間參數有效性validateattributes(varargin{1}, {'numeric'}, ...{'real','row','ncols',2,'<=',1,'>=', minBound}, ...['doppler(''', specType, ''', NormalizedFrequencyInterval)'], ...'NormalizedFrequencyInterval');% 檢查頻率區間是否遞增coder.internal.errorIf(diff(varargin{1}) < 0, 'comm:doppler:InvalidFreqInterval');freqInterval = varargin{1};elsefreqInterval = [0 1]; % 默認頻率區間end% 創建包含頻率區間的結構體s = struct('SpectrumType', specType, ...'NormalizedFrequencyInterval', freqInterval);case 'Gaussian' % 高斯頻譜narginchk(1, 2); % 驗證輸入參數數量if nargin == 2% 驗證標準差參數有效性validateattributes(varargin{1}, {'numeric'}, ...{'real','scalar','positive','finite'}, ...'doppler(''Gaussian'', NormalizedStandardDeviation)', ...'NormalizedStandardDeviation');stdDev = varargin{1};elsestdDev = 1/sqrt(2); % 默認標準差end% 創建包含標準差的結構體s = struct('SpectrumType', specType, ...'NormalizedStandardDeviation', stdDev);case 'BiGaussian' % 雙高斯頻譜narginchk(1, 7); % 驗證輸入參數數量% 檢查是否為參數-值對形式coder.internal.errorIf((mod(nargin - 1, 2) ~= 0), ...'comm:doppler:InputNotPVParis');% 創建默認雙高斯結構體s = struct('SpectrumType', specType, ...'NormalizedStandardDeviations', [1/sqrt(2), 1/sqrt(2)], ...'NormalizedCenterFrequencies', [0, 0], ...'PowerGains', [0.5, 0.5]);% 處理參數-值對輸入for i = 1 : 2: nargin-2% 驗證參數名稱有效性coder.internal.errorIf(~comm.internal.utilities.isCharOrStringScalar(varargin{i}), ...'comm:doppler:InvalidBiGaussianField');% 根據參數名處理不同字段switch varargin{i}case 'NormalizedStandardDeviations' % 歸一化標準差validateattributes(varargin{i+1}, {'numeric'}, ...{'real','row','ncols',2,'positive','finite'}, ...'doppler(''BiGaussian'', ''NormalizedStandardDeviations'', value)', ...'NormalizedStandardDeviations');s.NormalizedStandardDeviations = varargin{i+1};case 'NormalizedCenterFrequencies' % 歸一化中心頻率validateattributes(varargin{i+1}, {'numeric'}, ...{'real','row','ncols',2,'<=',1,'>=',-1}, ...'doppler(''BiGaussian'', ''NormalizedCenterFrequencies'', value)', ...'NormalizedCenterFrequencies');s.NormalizedCenterFrequencies = varargin{i+1};case 'PowerGains' % 功率增益validateattributes(varargin{i+1}, {'numeric'}, ...{'real','row','ncols',2,'nonnegative','finite'}, ...'doppler(''BiGaussian'', ''PowerGains'', value)', 'PowerGains');% 檢查增益是否全為零coder.internal.errorIf(isequal(varargin{i+1}, zeros(1, 2)), ...'comm:doppler:PowerGainsBothZeros');s.PowerGains = varargin{i+1};otherwise % 無效參數名coder.internal.errorIf(true, 'comm:doppler:InvalidBiGaussianField'); endendotherwise % 無效頻譜類型coder.internal.errorIf(true, 'comm:doppler:InvalidSpecType');
endend