A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
three-gpp-v2v-channel-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020, University of Padova, Dep. of Information Engineering, SIGNET lab
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8/*
9 * @file
10 * This is an example of how to configure the channel model classes to simulate
11 * a vehicular environment.
12 * The channel condition is determined using the model specified in [1], Table 6.2-1.
13 * The pathloss is determined using the model specified in [1], Table 6.2.1-1.
14 * The model for the fast fading is the one described in 3GPP TR 38.901 v15.0.0,
15 * the model parameters are those specified in [1], Table 6.2.3-1.
16 *
17 * This example generates the output file 'three-gpp-v2v-channel-example-output.txt'. Each row of
18 * the file is organized as follows: Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState
19 * SNR[dB] Pathloss[dB] We also provide a bash script which reads the output file and generates two
20 * figures:
21 * (i) three-gpp-v2v-channel-example-map.gif, a GIF representing the simulation scenario and vehicle
22 * mobility;
23 * (ii) three-gpp-v2v-channel-example-snr.png, which represents the behavior of the SNR.
24 *
25 * [1] 3GPP TR 37.885, v15.3.0
26 */
27
28#include "ns3/buildings-module.h"
29#include "ns3/core-module.h"
30#include "ns3/mobility-module.h"
31#include "ns3/network-module.h"
32#include "ns3/spectrum-signal-parameters.h"
33#include "ns3/three-gpp-channel-model.h"
34#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
35#include "ns3/three-gpp-v2v-propagation-loss-model.h"
36#include "ns3/uniform-planar-array.h"
37
38#include <fstream>
39
40using namespace ns3;
41
42/// the log component
43NS_LOG_COMPONENT_DEFINE("ThreeGppV2vChannelExample");
44
46 m_propagationLossModel; //!< the PropagationLossModel object
48 m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
49static Ptr<ChannelConditionModel> m_condModel; //!< the ChannelConditionModel object
50
51/**
52 * @brief A structure that holds the parameters for the ComputeSnr
53 * function. In this way the problem with the limited
54 * number of parameters of method Schedule is avoided.
55 */
57{
58 Ptr<MobilityModel> txMob; //!< the tx mobility model
59 Ptr<MobilityModel> rxMob; //!< the rx mobility model
60 Ptr<SpectrumSignalParameters> txParams; //!< the params of the tx signal
61 double noiseFigure; //!< the noise figure in dB
62 Ptr<PhasedArrayModel> txAntenna; //!< the tx antenna array
63 Ptr<PhasedArrayModel> rxAntenna; //!< the rx antenna array
64};
65
66/**
67 * Perform the beamforming using the DFT beamforming method
68 * @param txMob the mobility model of the node performing the beamforming
69 * @param thisAntenna the antenna object associated to thisDevice
70 * @param rxMob the mobility model of the node towards which will point the beam
71 */
72static void
74{
75 // compute the azimuth and the elevation angles
76 Angles completeAngle(rxMob->GetPosition(), txMob->GetPosition());
77 PhasedArrayModel::ComplexVector bf = thisAntenna->GetBeamformingVector(completeAngle);
78 thisAntenna->SetBeamformingVector(bf);
79}
80
81/**
82 * Compute the average SNR
83 * @param params A structure that holds a bunch of parameters needed by ComputeSnr function to
84 * calculate the average SNR
85 */
86static void
88{
89 // check the channel condition
90 Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition(params.txMob, params.rxMob);
91 // apply the pathloss
92 double propagationGainDb = m_propagationLossModel->CalcRxPower(0, params.txMob, params.rxMob);
93 NS_LOG_DEBUG("Pathloss " << -propagationGainDb << " dB");
94 double propagationGainLinear = std::pow(10.0, (propagationGainDb) / 10.0);
95 *(params.txParams->psd) *= propagationGainLinear;
96 // apply the fast fading and the beamforming gain
97 auto rxParams = m_spectrumLossModel->CalcRxPowerSpectralDensity(params.txParams,
98 params.txMob,
99 params.rxMob,
100 params.txAntenna,
101 params.rxAntenna);
102 Ptr<SpectrumValue> rxPsd = rxParams->psd;
103 NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxPsd) * 180e3) << " dB");
104
105 // create the noise psd
106 // taken from lte-spectrum-value-helper
107 const double kT_dBm_Hz = -174.0; // dBm/Hz
108 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
109 double noiseFigureLinear = std::pow(10.0, params.noiseFigure / 10.0);
110 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
111 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(params.txParams->psd->GetSpectrumModel());
112 (*noisePsd) = noisePowerSpectralDensity;
113 // log the average SNR
114 NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " dB");
115 // print the SNR and pathloss values in the three-gpp-v2v-channel-example-output.txt file
116 std::ofstream f;
117 f.open("three-gpp-v2v-channel-example-output.txt", std::ios::out | std::ios::app);
118 f << Simulator::Now().GetSeconds() << " " // time [s]
119 << params.txMob->GetPosition().x << " " << params.txMob->GetPosition().y << " "
120 << params.rxMob->GetPosition().x << " " << params.rxMob->GetPosition().y << " "
121 << cond->GetLosCondition() << " " // channel state
122 << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " " // SNR [dB]
123 << -propagationGainDb << std::endl; // pathloss [dB]
124 f.close();
125}
126
127/**
128 * Generates a GNU-plottable file representing the buildings deployed in the
129 * scenario
130 * @param filename the name of the output file
131 */
132void
134{
135 std::ofstream outFile;
136 outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
137 if (!outFile.is_open())
138 {
139 NS_LOG_ERROR("Can't open file " << filename);
140 return;
141 }
142 for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
143 {
144 Box box = (*it)->GetBoundaries();
145 outFile << box.xMin << " " << box.yMin << " " << box.xMax << " " << box.yMax << std::endl;
146 }
147}
148
149int
150main(int argc, char* argv[])
151{
152 double frequency = 28.0e9; // operating frequency in Hz
153 double txPow_dbm = 30.0; // tx power in dBm
154 double noiseFigure = 9.0; // noise figure in dB
155 Time simTime = Seconds(40); // simulation time
156 Time timeRes = MilliSeconds(10); // time resolution
157 std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
158 double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
159 double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
160 uint32_t numRb = 275; // number of resource blocks
161 uint32_t updatePeriodMs = 0;
162
163 CommandLine cmd(__FILE__);
164 cmd.AddValue("frequency", "operating frequency in Hz", frequency);
165 cmd.AddValue("txPow", "tx power in dBm", txPow_dbm);
166 cmd.AddValue("noiseFigure", "noise figure in dB", noiseFigure);
167 cmd.AddValue("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
168 cmd.AddValue("updatePeriodMs", "the channel update period", updatePeriodMs);
169 cmd.Parse(argc, argv);
170
171 // create the nodes
173 nodes.Create(2);
174
175 // create the antenna objects and set their dimensions
176 Ptr<PhasedArrayModel> txAntenna =
178 UintegerValue(2),
179 "NumRows",
180 UintegerValue(2),
181 "BearingAngle",
182 DoubleValue(-M_PI / 2));
183 Ptr<PhasedArrayModel> rxAntenna =
185 UintegerValue(2),
186 "NumRows",
187 UintegerValue(2),
188 "BearingAngle",
189 DoubleValue(M_PI / 2));
190
191 Ptr<MobilityModel> txMob;
192 Ptr<MobilityModel> rxMob;
193 if (scenario == "V2V-Urban")
194 {
195 // 3GPP defines that the maximum speed in urban scenario is 60 km/h
196 vScatt = 60 / 3.6;
197
198 // create a grid of buildings
199 double buildingSizeX = 250 - 3.5 * 2 - 3; // m
200 double buildingSizeY = 433 - 3.5 * 2 - 3; // m
201 double streetWidth = 20; // m
202 double buildingHeight = 10; // m
203 uint32_t numBuildingsX = 2;
204 uint32_t numBuildingsY = 2;
205 double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
206 double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
207
208 std::vector<Ptr<Building>> buildingVector;
209 for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
210 {
211 for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
212 {
213 Ptr<Building> building;
214 building = CreateObject<Building>();
215
216 building->SetBoundaries(
217 Box(buildingIdX * (buildingSizeX + streetWidth),
218 buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
219 buildingIdY * (buildingSizeY + streetWidth),
220 buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
221 0.0,
222 buildingHeight));
223 building->SetNRoomsX(1);
224 building->SetNRoomsY(1);
225 building->SetNFloors(1);
226 buildingVector.push_back(building);
227 }
228 }
229
230 // set the mobility model
231 double vTx = vScatt;
232 double vRx = vScatt / 2;
235 Time nextWaypoint;
236 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
237 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
238 nextWaypoint += Seconds((maxAxisY - streetWidth) / 2 / vTx);
239 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
240 Waypoint(nextWaypoint,
241 Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
242 nextWaypoint += Seconds((maxAxisX - streetWidth) / 2 / vTx);
243 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
244 Waypoint(nextWaypoint, Vector(0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
245 nextWaypoint = Seconds(0);
246 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
247 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
248 nextWaypoint += Seconds(maxAxisY / vRx);
249 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
250 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
251
252 nodes.Get(0)->AggregateObject(txMob);
253 nodes.Get(1)->AggregateObject(rxMob);
254
255 // create the channel condition model
257
258 // create the propagation loss model
260 }
261 else if (scenario == "V2V-Highway")
262 {
263 // Two vehicles are travelling one behid the other with constant velocity
264 // along the y axis. The distance between the two vehicles is 20 meters.
265
266 // 3GPP defines that the maximum speed in urban scenario is 140 km/h
267 vScatt = 140 / 3.6;
268 double vTx = vScatt;
269 double vRx = vScatt / 2;
270
273 txMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 20.0, 1.5));
274 txMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vTx, 0.0));
275 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 0.0, 1.5));
276 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vRx, 0.0));
277
278 nodes.Get(0)->AggregateObject(txMob);
279 nodes.Get(1)->AggregateObject(rxMob);
280
281 // create the channel condition model
283
284 // create the propagation loss model
286 }
287 else
288 {
289 NS_FATAL_ERROR("Unknown scenario");
290 }
291
292 m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(100)));
293
294 m_propagationLossModel->SetAttribute("Frequency", DoubleValue(frequency));
295 m_propagationLossModel->SetAttribute("ShadowingEnabled", BooleanValue(false));
296 m_propagationLossModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
297
298 // create the channel model
300 channelModel->SetAttribute("Scenario", StringValue(scenario));
301 channelModel->SetAttribute("Frequency", DoubleValue(frequency));
302 channelModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
303 channelModel->SetAttribute("vScatt", DoubleValue(vScatt));
304 channelModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(updatePeriodMs)));
305
306 // create the spectrum propagation loss model
308 "ChannelModel",
309 PointerValue(channelModel));
310
312
313 // set the beamforming vectors
314 DoBeamforming(txMob, txAntenna, rxMob);
315 DoBeamforming(rxMob, rxAntenna, txMob);
316
317 // create the tx power spectral density
318 Bands rbs;
319 double freqSubBand = frequency;
320 for (uint32_t n = 0; n < numRb; ++n)
321 {
322 BandInfo rb;
323 rb.fl = freqSubBand;
324 freqSubBand += (subCarrierSpacing * 12) / 2;
325 rb.fc = freqSubBand;
326 freqSubBand += (subCarrierSpacing * 12) / 2;
327 rb.fh = freqSubBand;
328 rbs.push_back(rb);
329 }
330 Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel>(rbs);
331 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
333 double txPow_w = std::pow(10., (txPow_dbm - 30) / 10);
334 double txPowDens = (txPow_w / (numRb * subCarrierSpacing * 12));
335 (*txPsd) = txPowDens;
336 txParams->psd = txPsd->Copy();
337
338 for (int i = 0; i < simTime / timeRes; i++)
339 {
340 ComputeSnrParams params{txMob, rxMob, txParams->Copy(), noiseFigure, txAntenna, rxAntenna};
341 Simulator::Schedule(timeRes * i, &ComputeSnr, params);
342 }
343
344 // initialize the output file
345 std::ofstream f;
346 f.open("three-gpp-v2v-channel-example-output.txt", std::ios::out);
347 f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]"
348 << std::endl;
349 f.close();
350
351 // print the list of buildings to file
352 PrintGnuplottableBuildingListToFile("three-gpp-v2v-channel-example-buildings.txt");
353
356 return 0;
357}
Class holding the azimuth and inclination angles of spherical coordinates.
Definition angles.h:107
AttributeValue implementation for Boolean.
Definition boolean.h:26
a 3d box
Definition box.h:24
double yMax
The y coordinate of the top bound of the box.
Definition box.h:105
double xMin
The x coordinate of the left bound of the box.
Definition box.h:99
double yMin
The y coordinate of the bottom bound of the box.
Definition box.h:103
double xMax
The x coordinate of the right bound of the box.
Definition box.h:101
static Iterator End()
static Iterator Begin()
static void Install(Ptr< Node > node)
Install the MobilityBuildingInfo to a node.
Parse command-line arguments.
Mobility model for which the current speed does not change once it has been set and until it is set a...
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
keep track of a set of node pointers.
ComplexMatrixArray ComplexVector
the underlying Valarray
AttributeValue implementation for Pointer.
Definition pointer.h:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
static void Run()
Run the simulation.
Definition simulator.cc:161
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:398
AttributeValue implementation for Time.
Definition nstime.h:1375
Hold an unsigned integer type.
Definition uinteger.h:34
a (time, location) pair.
Definition waypoint.h:25
Waypoint-based mobility model.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:246
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:454
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1290
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< BandInfo > Bands
Container of BandInfo.
double Sum(const SpectrumValue &x)
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
A structure that holds the parameters for the ComputeSnr function.
ComputeSnrParams(Ptr< MobilityModel > pTxMob, Ptr< MobilityModel > pRxMob, double pTxPow, double pNoiseFigure, Ptr< PhasedArrayModel > pTxAntenna, Ptr< PhasedArrayModel > pRxAntenna, double pFrequency, double pBandwidth, double pResourceBlockBandwidth)
Constructor.
Ptr< PhasedArrayModel > txAntenna
the tx antenna array
Ptr< MobilityModel > rxMob
the rx mobility model
Ptr< SpectrumSignalParameters > txParams
the params of the tx signal
double noiseFigure
the noise figure in dB
Ptr< PhasedArrayModel > rxAntenna
the rx antenna array
Ptr< MobilityModel > txMob
the tx mobility model
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
static Ptr< ChannelConditionModel > m_condModel
the ChannelConditionModel object
static Ptr< ThreeGppPropagationLossModel > m_propagationLossModel
the log component
static void ComputeSnr(const ComputeSnrParams &params)
Compute the average SNR.
static void DoBeamforming(Ptr< MobilityModel > txMob, Ptr< PhasedArrayModel > thisAntenna, Ptr< MobilityModel > rxMob)
Perform the beamforming using the DFT beamforming method.
void PrintGnuplottableBuildingListToFile(std::string filename)
Generates a GNU-plottable file representing the buildings deployed in the scenario.
static Ptr< ThreeGppSpectrumPropagationLossModel > m_spectrumLossModel
the SpectrumPropagationLossModel object