Generation of Satellite Channels
This script demonstrates the parametrization of the channel model to generate time-continuous sequences for a satellite scenario.
Contents
Setting up the Simulation Parameters
First, we set up the general simulation parameters. We choose a center frequency of 2.1 GHz. We also want to use drifting in order to get the correct delays and angles for the time-continuous simulation. A sample density of 2.5 ensures that the channel coefficients can be interpolated to different playback speeds later on.
close all clear all set(0,'defaultTextFontSize', 14) % Set default font size for the plots set(0,'defaultAxesFontSize', 14) s = simulation_parameters; % Basic simulation parameters s.center_frequency = 2.185e9; s.sample_density = 0.25; RandStream.setGlobalStream(RandStream('mt19937ar','seed',1));
Creating a random Track and defining states along the track
Next, we generate a simulation track. A track describes the movement of a mobile terminal. It is composed of an ordered list of positions. During the simulation, one snapshot is generated for each position on the track. Later on, the generation of the track is done by the state sequence generator. Here, we implement a simple version of the sequence generator to generate a random track.
We first create a set of streets with different length. We assume a normal distribution of the street length where the parameters mu and sigma were fitted from random distances between two crossings in central Berlin (measured with Google earth).
street_length_mu = 187; % Average street length in m street_length_sigma = 83; min_street_length = 50; turn_probability = 0.4; % The prob. that the car turns at a crossing curve_radius = 10; % The curve radius in m diro = rand * 2*pi; % Random start direction
For the given parameters, we calculate a list of points along the track that resemble the street grid and the turns at crossings.
point = 0; % The start point (always at [0,0]) m = 1; % A counter for the points for n = 1:3 % We simulate 3 street segments % Get a random street length drawn from the distribution defined above street_length = randn*street_length_sigma + street_length_mu; while street_length < min_street_length street_length = randn*street_length_sigma + street_length_mu; end % Get 3 points along the street point(m+1) = point(m) + exp(1j*diro) * street_length*0.1; point(m+2) = point(m) + exp(1j*diro) * street_length*0.9; point(m+3) = point(m) + exp(1j*diro) * street_length; m=m+3; % At a crossing, the car could change its direction. This is % modeled here if rand < turn_probability dirn = diro + sign( rand-0.5 ) * pi/2 + randn*pi/12; point(m+1) = point(m) + curve_radius*( exp(1j*diro) + exp(1j*dirn) ); diro = dirn; m=m+1; end end
Next, we create a track object and pass the points along the track. We then use the internal interpolation functions to interpolate the track to 1 point per meter.
t = track; % Create a track object t.positions = [ real(point) ; imag(point) ; zeros(1,numel(point))]; t.interpolate_positions( 1 ); % Interpolate to 1 point per meter
We now assemble a rudimentary state sequence generator that generates different states along the track. We first define the distribution parameters of the segment length and then calculate the segments themselves. The two possible states are "MIMOSA_10-45_LOS" which stands for LOS or good state and "MIMOSA_10-45_NLOS" for NLOS or bad state.
segment_length_mu = 30; % Average segment length in m segment_length_sigma = 12; % Standard deviation in m min_segment_length = 10; % Minimum segment length in m % Now we define the segments (the states) along the track ind = 1; while ind < t.no_snapshots % Each scenario has a 50% probability if rand < 0.5 t.scenario{ t.no_segments } = 'MIMOSA_10-45_LOS' ; else t.scenario{ t.no_segments } = 'MIMOSA_10-45_NLOS' ; end % Get the length of the current segment segment_length = randn*segment_length_sigma + segment_length_mu; while segment_length<min_segment_length segment_length = randn*segment_length_sigma + segment_length_mu; end segment_length = round(segment_length); % Segment length ind = ind + segment_length; % Start of next segment if ind < t.no_snapshots % Exception for the last segment t.no_segments = t.no_segments + 1; t.segment_index( t.no_segments ) = ind; end end
Finally, we interpolate the track to the given sample density (2 samples per half-wave-length) and plot the track.
t.interpolate_positions( s.samples_per_meter ); t.visualize;

Defining Antenna Arrays
In the third step, we set up our antenna arrays for the transmitter at the satellite and the receiver. We use synthetic dipole antennas for this case. Two dipoles are crossed by an angle of 90 degree. The signal is then split and fed with a 90 degree phase shift to both elements generating RHCP and LHCP signals.
% Create a patch antenna with 120 degree opening a = array('custom',120,120,0); % Copy element 1 to element 2 - the resulting antenna array has two % elements, both dipoles. a.copy_element(1,2); % Rotate the second pattern by 90 degree around the x-axis. a.rotate_pattern(90,'x',2); % Set the coupling between the elements. The Tx-signal for the first % element is shifted by +90 degree out of phase and put on the second element. % The signal for the second element is shifted by -90 degree and copied to the % first element. Both antennas thus radiate a RHCP and a LHCP wave. a.coupling = 1/sqrt(2) * [1 1;1j -1j]; % Create a copy of the array for the receiver. b = a.copy_objects; b.coupling = 1/sqrt(2) * [1 1;1j -1j]; % Rotate the receive antenna array to face sky-wards. b.rotate_pattern(-90,'y'); b.visualize; % Plot the pattern of the Rx-Antenna


Setting up the Layout
In this step, we combine the track, the antennas and the position of the satellite into a simulation layout. A layout object contains all the geometric information that are necessary to run the simulation. First, we define the position of the satellite. Since the model uses Cartesian coordinates, we have to transform the position of the satellite first.
l = layout( s ); % Create a new layout % Choose a random satellite position (Astra 2, seen from Berlin). % The distance only needs to be big enough to ensure insignificant changes % in the reception angle on the ground. sat_el = 28.4; % Elevation angle sat_az = 161.6; % Azimuth angle (South = 180 degree) rx_latitude = 51; % Latitude of the Rx % Approximate the satelite distance for GEO orbit dist_x = 35786 + rx_latitude/90 * 6384; % [km] dist_y = (1-rx_latitude/90) * 6384; % [km] sat_dist = sqrt(dist_x^2 + dist_y^2); % [km] sat_dist = sat_dist*1e3; % [m] % Transform angles to Cartesian coordinates sat_x = sat_dist * cosd(sat_el) * cosd( -sat_az+90 ); sat_y = sat_dist * cosd(sat_el) * sind( -sat_az+90 ); sat_z = sat_dist * sind(sat_el); % We also turn the antenna of the satellite so it points to the receiver. a.rotate_pattern( sat_el , 'y' ); a.rotate_pattern( 270-sat_az , 'z' ); % Set the satellite position in the layout l.tx_position = [ sat_x ; sat_y ; sat_z ]; l.track = t; % Set the track for the receiver l.tx_array = a; % Set the tx_array l.rx_array = b; % Set the rx_array
Setting up scenario parameters
Next, the large scale parameters are set. The first line calls "l.create_parameter_sets", a built-in function that processes the data in the layout and returns a new "parameter_set" object "p". "p" is an array with two elements. One of them contains all the parameters for the good state (LOS) and one for the bad state (NLOS).
p = l.create_parameter_sets(0);
Each parameter set has two different kinds of parameters. One for the scenario and one for the current state. For example, a scenario might have an average RMS Delay spread of 158 ns plus a certain variance which defines a range for the RMSDS. In addition to that, there are cross-correlations with other parameters such as the angular spread at the transmitter. All those parameters are stored in the "scenpar" property. For the good state, that parameters are:
Sl = strcmp( { p(1).name , p(2).name } ,'MIMOSA-10-45-LOS_Tx01' ); % Select good state p(Sl).scenpar % Show parameter list
ans = NumClusters: 8 r_DS: 2.5000 PerClusterAS_D: 6.2000e-07 PerClusterAS_A: 12 PerClusterES_D: 1.9000e-07 PerClusterES_A: 7 LOS_scatter_radius: 0 LNS_ksi: 3 xpr_mu: 11.9000 xpr_sigma: 5.5000 DS_mu: -7.5000 DS_sigma: 0.3000 AS_D_mu: -4.6000 AS_D_sigma: 0.1000 AS_A_mu: 1.5000 AS_A_sigma: 0.2000 ES_D_mu: -5.1200 ES_D_sigma: 0.1000 ES_A_mu: 1.4000 ES_A_sigma: 0.1000 SF_sigma: 3.6000 KF_mu: 15.5000 KF_sigma: 5.9000 DS_lambda: 30.5000 AS_D_lambda: 1000 AS_A_lambda: 31.5000 ES_D_lambda: 1000 ES_A_lambda: 6 SF_lambda: 35 KF_lambda: 4.5000 asD_ds: 0 asA_ds: 0.6100 asA_sf: 0.5600 asD_sf: 0 ds_sf: 0.4300 asD_asA: 0 asD_kf: 0 asA_kf: -0.4400 ds_kf: -0.4600 sf_kf: -0.3000 esD_ds: 0 esA_ds: -0.0500 esA_sf: 0.1800 esD_sf: 0 esD_esA: 0 esD_asD: 0 esD_asA: 0 esA_asD: 0 esA_asA: 0.1500 esD_kf: 0 esA_kf: -0.0300
Note here, that the values are given for a log-normal distribution. Thus, the RMSDS in nanoseconds follows from
10^( p(Sl).scenpar.DS_mu ) * 1e9
ans = 31.6228
Each parameter on that list can be changed by just assigning it a new value. Here, we set the number of clusters for the LOS scenario to 7. Note that the default settings are stored in files in the sub-folder "config" of the channel model folder. Here, the default settings can be permanently set.
After a change, the parameters of the segments need to be updated. This is done by calling the "update_parameters" method.
p(Sl).scenpar.NumClusters = 7; p.update_parameters;
Parameters [oooooooooooooooooooooooooooooooooooooooooooooooooo] 14 seconds
When "update_parameter" is called, the specific parameters for each segment are generated. E.g. each segment gets assigned a RMS Delay Spread and other values which are drawn from the statistics defined in scenpar. For the LOS segments, the individual RMSDS values for each segment are:
rmsds = p(Sl).ds*1e9 average = mean(p(Sl).ds*1e9)
rmsds = Columns 1 through 7 43.3811 30.5744 49.1044 10.6780 32.8010 33.2708 13.7404 Columns 8 through 11 8.7877 10.6605 11.5351 35.5414 average = 25.4613
Generate channel coefficients
Next, we generate the channel coefficients. This is a lengthy task. The next line then combines the channels of the individual segments into a time-continuous channel. Here, the parameter (0.2) sets the length of the overlap region between two segments. In this case, it is 20%.
c = p.get_channels; % Generate coefficients cn = c.merge(0.2); % Combine segments
Channels [oooooooooooooooooooooooooooooooooooooooooooooooooo] 20 seconds Merging [oooooooooooooooooooooooooooooooooooooooooooooooooo] 2 seconds
Evaluation of the data
The next two plots show some basic evaluations of the generated coefficients. The first plot shows the received power for the 4 MIMO links along the track. The plot shows the differences between the LOS and NLOS segments and the cross-pol discrimination between the MIMO links. The average path loss for LOS was set to -95 dB and for NLOS -113 dB.
dist = (1:cn.no_snap)*t.get_length/cn.no_snap; ind = find(strcmp(t.scenario,'MIMOSA_10-45_LOS')); los = []; for n = 1:numel(ind) start = t.segment_index(ind(n)); if n==numel(ind) try stop = t.segment_index(ind(n)+1); catch stop = t.no_snapshots; end else stop = t.segment_index(ind(n)+1); end los = [los start:stop]; end power = reshape( 10*log10( squeeze(sum( abs(cn.coeff).^2 , 3 )) ) , 4,[]); mi = min(reshape(power,[],1)) - 5; ma = max(reshape(power,[],1)) + 5; ar = ones(1,cn.no_snap) * ma; ar(los) = mi; figure('Position',[ 100 , 100 , 1000 , 700]); a = area(dist,ar); set(a(1),'FaceColor',[0.7 0.9 0.7]); set(a,'LineStyle','none') hold on plot(dist,power') hold off xlabel('Track [m]'); ylabel('Received Power per MIMO LINK [dB]'); axis([0 t.get_length mi ma]) legend('LOS','P_{11}','P_{12}','P_{21}','P_{22}',4) box on title('Received power along the track')

The next plot shows the RMS delay spread along the path for the first MIMO element. Again, shaded ares are for the LOS segments.
pow_tap = abs(squeeze(cn.coeff(1,1,:,:))).^2; pow_sum = sum( pow_tap,1 ); mean_delay = sum( pow_tap.*cn.delay ,1) ./ pow_sum; ds = sqrt( sum( pow_tap.*cn.delay.^2 ,1)./ pow_sum - mean_delay.^2 ); ar = zeros(1,cn.no_snap); ar(los) = 10000; figure('Position',[ 100 , 100 , 1000 , 700]); a = area(dist,ar); set(a(1),'FaceColor',[0.7 0.9 0.7]); set(a,'LineStyle','none') hold on plot( dist , ds*1e9 ) hold off ma = 1e9*( max(ds)+0.1*max(ds) ); axis([0 t.get_length 0 ma]) xlabel('Track [m]'); ylabel('Delay Spread [ns]'); legend('LOS','\sigma_\tau',1) title('Position dependant delay spread');

close all disp(['QuaDRiGa Version: ',simulation_parameters.version])
QuaDRiGa Version: 1.0.7-191