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 * This is an example on how to configure the channel model classes to simulate
10 * a vehicular environment.
11 * The channel condition is determined using the model specified in [1], Table 6.2-1.
12 * The pathloss is determined using the model specified in [1], Table 6.2.1-1.
13 * The model for the fast fading is the one described in 3GPP TR 38.901 v15.0.0,
14 * the model parameters are those specified in [1], Table 6.2.3-1.
15 *
16 * This example generates the output file 'example-output.txt'. Each row of the
17 * file is organized as follows:
18 * Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]
19 * We also provide a bash script which reads the output file and generates two
20 * figures:
21 * (i) map.gif, a GIF representing the simulation scenario and vehicle mobility;
22 * (ii) snr.png, which represents the behavior of the SNR.
23 *
24 * [1] 3GPP TR 37.885, v15.3.0
25 */
26
27#include "ns3/buildings-module.h"
28#include "ns3/core-module.h"
29#include "ns3/mobility-module.h"
30#include "ns3/network-module.h"
31#include "ns3/spectrum-signal-parameters.h"
32#include "ns3/three-gpp-channel-model.h"
33#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
34#include "ns3/three-gpp-v2v-propagation-loss-model.h"
35#include "ns3/uniform-planar-array.h"
36
37#include <fstream>
38
39using namespace ns3;
40
41NS_LOG_COMPONENT_DEFINE("ThreeGppV2vChannelExample");
42
44 m_propagationLossModel; //!< the PropagationLossModel object
46 m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
47static Ptr<ChannelConditionModel> m_condModel; //!< the ChannelConditionModel object
48
49/*
50 * \brief A structure that holds the parameters for the ComputeSnr
51 * function. In this way the problem with the limited
52 * number of parameters of method Schedule is avoided.
53 */
55{
56 Ptr<MobilityModel> txMob; //!< the tx mobility model
57 Ptr<MobilityModel> rxMob; //!< the rx mobility model
58 Ptr<SpectrumSignalParameters> txParams; //!< the params of the tx signal
59 double noiseFigure; //!< the noise figure in dB
60 Ptr<PhasedArrayModel> txAntenna; //!< the tx antenna array
61 Ptr<PhasedArrayModel> rxAntenna; //!< the rx antenna array
62};
63
64/**
65 * Perform the beamforming using the DFT beamforming method
66 * \param thisDevice the device performing the beamforming
67 * \param thisAntenna the antenna object associated to thisDevice
68 * \param otherDevice the device towards which point the beam
69 */
70static void
72 Ptr<PhasedArrayModel> thisAntenna,
73 Ptr<NetDevice> otherDevice)
74{
76
77 // retrieve the position of the two devices
78 Vector aPos = thisDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
79 Vector bPos = otherDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
80
81 // compute the azimuth and the elevation angles
82 Angles completeAngle(bPos, aPos);
83
84 PhasedArrayModel::ComplexVector bf = thisAntenna->GetBeamformingVector(completeAngle);
85 thisAntenna->SetBeamformingVector(bf);
86}
87
88/**
89 * Compute the average SNR
90 * \param params A structure that holds a bunch of parameters needed by ComputSnr function to
91 * calculate the average SNR
92 */
93static void
95{
96 // check the channel condition
97 Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition(params.txMob, params.rxMob);
98
99 // apply the pathloss
100 double propagationGainDb = m_propagationLossModel->CalcRxPower(0, params.txMob, params.rxMob);
101 NS_LOG_DEBUG("Pathloss " << -propagationGainDb << " dB");
102 double propagationGainLinear = std::pow(10.0, (propagationGainDb) / 10.0);
103 *(params.txParams->psd) *= propagationGainLinear;
104
105 // apply the fast fading and the beamforming gain
106 auto rxParams = m_spectrumLossModel->CalcRxPowerSpectralDensity(params.txParams,
107 params.txMob,
108 params.rxMob,
109 params.txAntenna,
110 params.rxAntenna);
111 Ptr<SpectrumValue> rxPsd = rxParams->psd;
112 NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxPsd) * 180e3) << " dB");
113
114 // create the noise psd
115 // taken from lte-spectrum-value-helper
116 const double kT_dBm_Hz = -174.0; // dBm/Hz
117 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
118 double noiseFigureLinear = std::pow(10.0, params.noiseFigure / 10.0);
119 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
120 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(params.txParams->psd->GetSpectrumModel());
121 (*noisePsd) = noisePowerSpectralDensity;
122
123 // compute the SNR
124 NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " dB");
125
126 // print the SNR and pathloss values in the snr-trace.txt file
127 std::ofstream f;
128 f.open("example-output.txt", std::ios::out | std::ios::app);
129 f << Simulator::Now().GetSeconds() << " " // time [s]
130 << params.txMob->GetPosition().x << " " << params.txMob->GetPosition().y << " "
131 << params.rxMob->GetPosition().x << " " << params.rxMob->GetPosition().y << " "
132 << cond->GetLosCondition() << " " // channel state
133 << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " " // SNR [dB]
134 << -propagationGainDb << std::endl; // pathloss [dB]
135 f.close();
136}
137
138/**
139 * Generates a GNU-plottable file representing the buildings deployed in the
140 * scenario
141 * \param filename the name of the output file
142 */
143void
145{
146 std::ofstream outFile;
147 outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
148 if (!outFile.is_open())
149 {
150 NS_LOG_ERROR("Can't open file " << filename);
151 return;
152 }
153 uint32_t index = 0;
154 for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
155 {
156 ++index;
157 Box box = (*it)->GetBoundaries();
158 outFile << "set object " << index << " rect from " << box.xMin << "," << box.yMin << " to "
159 << box.xMax << "," << box.yMax << std::endl;
160 }
161}
162
163int
164main(int argc, char* argv[])
165{
166 double frequency = 28.0e9; // operating frequency in Hz
167 double txPow_dbm = 30.0; // tx power in dBm
168 double noiseFigure = 9.0; // noise figure in dB
169 Time simTime = Seconds(40); // simulation time
170 Time timeRes = MilliSeconds(10); // time resolution
171 std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
172 double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
173 double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
174 uint32_t numRb = 275; // number of resource blocks
175
176 CommandLine cmd(__FILE__);
177 cmd.AddValue("frequency", "operating frequency in Hz", frequency);
178 cmd.AddValue("txPow", "tx power in dBm", txPow_dbm);
179 cmd.AddValue("noiseFigure", "noise figure in dB", noiseFigure);
180 cmd.AddValue("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
181 cmd.Parse(argc, argv);
182
183 // create the nodes
185 nodes.Create(2);
186
187 // create the tx and rx devices
190
191 // associate the nodes and the devices
192 nodes.Get(0)->AddDevice(txDev);
193 txDev->SetNode(nodes.Get(0));
194 nodes.Get(1)->AddDevice(rxDev);
195 rxDev->SetNode(nodes.Get(1));
196
197 // create the antenna objects and set their dimensions
198 Ptr<PhasedArrayModel> txAntenna =
200 UintegerValue(2),
201 "NumRows",
202 UintegerValue(2),
203 "BearingAngle",
204 DoubleValue(-M_PI / 2));
205 Ptr<PhasedArrayModel> rxAntenna =
207 UintegerValue(2),
208 "NumRows",
209 UintegerValue(2),
210 "BearingAngle",
211 DoubleValue(M_PI / 2));
212
213 Ptr<MobilityModel> txMob;
214 Ptr<MobilityModel> rxMob;
215 if (scenario == "V2V-Urban")
216 {
217 // 3GPP defines that the maximum speed in urban scenario is 60 km/h
218 vScatt = 60 / 3.6;
219
220 // create a grid of buildings
221 double buildingSizeX = 250 - 3.5 * 2 - 3; // m
222 double buildingSizeY = 433 - 3.5 * 2 - 3; // m
223 double streetWidth = 20; // m
224 double buildingHeight = 10; // m
225 uint32_t numBuildingsX = 2;
226 uint32_t numBuildingsY = 2;
227 double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
228 double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
229
230 std::vector<Ptr<Building>> buildingVector;
231 for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
232 {
233 for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
234 {
235 Ptr<Building> building;
236 building = CreateObject<Building>();
237
238 building->SetBoundaries(
239 Box(buildingIdX * (buildingSizeX + streetWidth),
240 buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
241 buildingIdY * (buildingSizeY + streetWidth),
242 buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
243 0.0,
244 buildingHeight));
245 building->SetNRoomsX(1);
246 building->SetNRoomsY(1);
247 building->SetNFloors(1);
248 buildingVector.push_back(building);
249 }
250 }
251
252 // set the mobility model
253 double vTx = vScatt;
254 double vRx = vScatt / 2;
257 Time nextWaypoint = Seconds(0.0);
258 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
259 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
260 nextWaypoint += Seconds((maxAxisY - streetWidth) / 2 / vTx);
261 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
262 Waypoint(nextWaypoint,
263 Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
264 nextWaypoint += Seconds((maxAxisX - streetWidth) / 2 / vTx);
265 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
266 Waypoint(nextWaypoint, Vector(0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
267 nextWaypoint = Seconds(0.0);
268 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
269 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
270 nextWaypoint += Seconds(maxAxisY / vRx);
271 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
272 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
273
274 nodes.Get(0)->AggregateObject(txMob);
275 nodes.Get(1)->AggregateObject(rxMob);
276
277 // create the channel condition model
279
280 // create the propagation loss model
282 }
283 else if (scenario == "V2V-Highway")
284 {
285 // Two vehicles are travelling one behid the other with constant velocity
286 // along the y axis. The distance between the two vehicles is 20 meters.
287
288 // 3GPP defines that the maximum speed in urban scenario is 140 km/h
289 vScatt = 140 / 3.6;
290 double vTx = vScatt;
291 double vRx = vScatt / 2;
292
295 txMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 20.0, 1.5));
296 txMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vTx, 0.0));
297 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 0.0, 1.5));
298 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vRx, 0.0));
299
300 nodes.Get(0)->AggregateObject(txMob);
301 nodes.Get(1)->AggregateObject(rxMob);
302
303 // create the channel condition model
305
306 // create the propagation loss model
308 }
309 else
310 {
311 NS_FATAL_ERROR("Unknown scenario");
312 }
313
314 m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(100)));
315
316 m_propagationLossModel->SetAttribute("Frequency", DoubleValue(frequency));
317 m_propagationLossModel->SetAttribute("ShadowingEnabled", BooleanValue(false));
318 m_propagationLossModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
319
320 // create the channel model
322 channelModel->SetAttribute("Scenario", StringValue(scenario));
323 channelModel->SetAttribute("Frequency", DoubleValue(frequency));
324 channelModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
325 channelModel->SetAttribute("vScatt", DoubleValue(vScatt));
326
327 // create the spectrum propagation loss model
329 "ChannelModel",
330 PointerValue(channelModel));
331
333
334 // set the beamforming vectors
335 DoBeamforming(txDev, txAntenna, rxDev);
336 DoBeamforming(rxDev, rxAntenna, txDev);
337
338 // create the tx power spectral density
339 Bands rbs;
340 double freqSubBand = frequency;
341 for (uint32_t n = 0; n < numRb; ++n)
342 {
343 BandInfo rb;
344 rb.fl = freqSubBand;
345 freqSubBand += subCarrierSpacing / 2;
346 rb.fc = freqSubBand;
347 freqSubBand += subCarrierSpacing / 2;
348 rb.fh = freqSubBand;
349 rbs.push_back(rb);
350 }
351 Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel>(rbs);
352 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
354 double txPow_w = std::pow(10., (txPow_dbm - 30) / 10);
355 double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
356 (*txPsd) = txPowDens;
357 txParams->psd = txPsd->Copy();
358
359 for (int i = 0; i < simTime / timeRes; i++)
360 {
361 ComputeSnrParams params{txMob, rxMob, txParams, noiseFigure, txAntenna, rxAntenna};
362 Simulator::Schedule(timeRes * i, &ComputeSnr, params);
363 }
364
365 // initialize the output file
366 std::ofstream f;
367 f.open("example-output.txt", std::ios::out);
368 f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]"
369 << std::endl;
370 f.close();
371
372 // print the list of buildings to file
374
377 return 0;
378}
Class holding the azimuth and inclination angles of spherical coordinates.
Definition angles.h:107
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 the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition node.cc:124
void AggregateObject(Ptr< Object > other)
Aggregate two Objects together.
Definition object.cc:298
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
Hold variables of type string.
Definition string.h:45
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
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:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
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:436
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
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.
Ptr< PhasedArrayModel > txAntenna
the tx antenna array
Ptr< MobilityModel > rxMob
the rx mobility model
double noiseFigure
the noise figure in dB
Ptr< SpectrumSignalParameters > txParams
the params of the tx signal
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 PropagationLossModel object
static void DoBeamforming(Ptr< NetDevice > thisDevice, Ptr< PhasedArrayModel > thisAntenna, Ptr< NetDevice > otherDevice)
Perform the beamforming using the DFT beamforming method.
static void ComputeSnr(const ComputeSnrParams &params)
Compute the average SNR.
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