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
41/// the log component
42NS_LOG_COMPONENT_DEFINE("ThreeGppV2vChannelExample");
43
45 m_propagationLossModel; //!< the PropagationLossModel object
47 m_spectrumLossModel; //!< the SpectrumPropagationLossModel object
48static Ptr<ChannelConditionModel> m_condModel; //!< the ChannelConditionModel object
49
50/**
51 * @brief A structure that holds the parameters for the ComputeSnr
52 * function. In this way the problem with the limited
53 * number of parameters of method Schedule is avoided.
54 */
56{
57 Ptr<MobilityModel> txMob; //!< the tx mobility model
58 Ptr<MobilityModel> rxMob; //!< the rx mobility model
59 Ptr<SpectrumSignalParameters> txParams; //!< the params of the tx signal
60 double noiseFigure; //!< the noise figure in dB
61 Ptr<PhasedArrayModel> txAntenna; //!< the tx antenna array
62 Ptr<PhasedArrayModel> rxAntenna; //!< the rx antenna array
63};
64
65/**
66 * Perform the beamforming using the DFT beamforming method
67 * @param thisDevice the device performing the beamforming
68 * @param thisAntenna the antenna object associated to thisDevice
69 * @param otherDevice the device towards which point the beam
70 */
71static void
73 Ptr<PhasedArrayModel> thisAntenna,
74 Ptr<NetDevice> otherDevice)
75{
77
78 // retrieve the position of the two devices
79 Vector aPos = thisDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
80 Vector bPos = otherDevice->GetNode()->GetObject<MobilityModel>()->GetPosition();
81
82 // compute the azimuth and the elevation angles
83 Angles completeAngle(bPos, aPos);
84
85 PhasedArrayModel::ComplexVector bf = thisAntenna->GetBeamformingVector(completeAngle);
86 thisAntenna->SetBeamformingVector(bf);
87}
88
89/**
90 * Compute the average SNR
91 * @param params A structure that holds a bunch of parameters needed by ComputSnr function to
92 * calculate the average SNR
93 */
94static void
96{
97 // check the channel condition
98 Ptr<ChannelCondition> cond = m_condModel->GetChannelCondition(params.txMob, params.rxMob);
99
100 // apply the pathloss
101 double propagationGainDb = m_propagationLossModel->CalcRxPower(0, params.txMob, params.rxMob);
102 NS_LOG_DEBUG("Pathloss " << -propagationGainDb << " dB");
103 double propagationGainLinear = std::pow(10.0, (propagationGainDb) / 10.0);
104 *(params.txParams->psd) *= propagationGainLinear;
105
106 // apply the fast fading and the beamforming gain
107 auto rxParams = m_spectrumLossModel->CalcRxPowerSpectralDensity(params.txParams,
108 params.txMob,
109 params.rxMob,
110 params.txAntenna,
111 params.rxAntenna);
112 Ptr<SpectrumValue> rxPsd = rxParams->psd;
113 NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxPsd) * 180e3) << " dB");
114
115 // create the noise psd
116 // taken from lte-spectrum-value-helper
117 const double kT_dBm_Hz = -174.0; // dBm/Hz
118 double kT_W_Hz = std::pow(10.0, (kT_dBm_Hz - 30) / 10.0);
119 double noiseFigureLinear = std::pow(10.0, params.noiseFigure / 10.0);
120 double noisePowerSpectralDensity = kT_W_Hz * noiseFigureLinear;
121 Ptr<SpectrumValue> noisePsd = Create<SpectrumValue>(params.txParams->psd->GetSpectrumModel());
122 (*noisePsd) = noisePowerSpectralDensity;
123
124 // compute the SNR
125 NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " dB");
126
127 // print the SNR and pathloss values in the snr-trace.txt file
128 std::ofstream f;
129 f.open("example-output.txt", std::ios::out | std::ios::app);
130 f << Simulator::Now().GetSeconds() << " " // time [s]
131 << params.txMob->GetPosition().x << " " << params.txMob->GetPosition().y << " "
132 << params.rxMob->GetPosition().x << " " << params.rxMob->GetPosition().y << " "
133 << cond->GetLosCondition() << " " // channel state
134 << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " " // SNR [dB]
135 << -propagationGainDb << std::endl; // pathloss [dB]
136 f.close();
137}
138
139/**
140 * Generates a GNU-plottable file representing the buildings deployed in the
141 * scenario
142 * @param filename the name of the output file
143 */
144void
146{
147 std::ofstream outFile;
148 outFile.open(filename, std::ios_base::out | std::ios_base::trunc);
149 if (!outFile.is_open())
150 {
151 NS_LOG_ERROR("Can't open file " << filename);
152 return;
153 }
154 for (auto it = BuildingList::Begin(); it != BuildingList::End(); ++it)
155 {
156 Box box = (*it)->GetBoundaries();
157 outFile << box.xMin << " " << box.yMin << " " << box.xMax << " " << box.yMax << std::endl;
158 }
159}
160
161int
162main(int argc, char* argv[])
163{
164 double frequency = 28.0e9; // operating frequency in Hz
165 double txPow_dbm = 30.0; // tx power in dBm
166 double noiseFigure = 9.0; // noise figure in dB
167 Time simTime = Seconds(40); // simulation time
168 Time timeRes = MilliSeconds(10); // time resolution
169 std::string scenario = "V2V-Urban"; // 3GPP propagation scenario, V2V-Urban or V2V-Highway
170 double vScatt = 0; // maximum speed of the vehicles in the scenario [m/s]
171 double subCarrierSpacing = 60e3; // subcarrier spacing in kHz
172 uint32_t numRb = 275; // number of resource blocks
173
174 CommandLine cmd(__FILE__);
175 cmd.AddValue("frequency", "operating frequency in Hz", frequency);
176 cmd.AddValue("txPow", "tx power in dBm", txPow_dbm);
177 cmd.AddValue("noiseFigure", "noise figure in dB", noiseFigure);
178 cmd.AddValue("scenario", "3GPP propagation scenario, V2V-Urban or V2V-Highway", scenario);
179 cmd.Parse(argc, argv);
180
181 // create the nodes
183 nodes.Create(2);
184
185 // create the tx and rx devices
188
189 // associate the nodes and the devices
190 nodes.Get(0)->AddDevice(txDev);
191 txDev->SetNode(nodes.Get(0));
192 nodes.Get(1)->AddDevice(rxDev);
193 rxDev->SetNode(nodes.Get(1));
194
195 // create the antenna objects and set their dimensions
196 Ptr<PhasedArrayModel> txAntenna =
198 UintegerValue(2),
199 "NumRows",
200 UintegerValue(2),
201 "BearingAngle",
202 DoubleValue(-M_PI / 2));
203 Ptr<PhasedArrayModel> rxAntenna =
205 UintegerValue(2),
206 "NumRows",
207 UintegerValue(2),
208 "BearingAngle",
209 DoubleValue(M_PI / 2));
210
211 Ptr<MobilityModel> txMob;
212 Ptr<MobilityModel> rxMob;
213 if (scenario == "V2V-Urban")
214 {
215 // 3GPP defines that the maximum speed in urban scenario is 60 km/h
216 vScatt = 60 / 3.6;
217
218 // create a grid of buildings
219 double buildingSizeX = 250 - 3.5 * 2 - 3; // m
220 double buildingSizeY = 433 - 3.5 * 2 - 3; // m
221 double streetWidth = 20; // m
222 double buildingHeight = 10; // m
223 uint32_t numBuildingsX = 2;
224 uint32_t numBuildingsY = 2;
225 double maxAxisX = (buildingSizeX + streetWidth) * numBuildingsX;
226 double maxAxisY = (buildingSizeY + streetWidth) * numBuildingsY;
227
228 std::vector<Ptr<Building>> buildingVector;
229 for (uint32_t buildingIdX = 0; buildingIdX < numBuildingsX; ++buildingIdX)
230 {
231 for (uint32_t buildingIdY = 0; buildingIdY < numBuildingsY; ++buildingIdY)
232 {
233 Ptr<Building> building;
234 building = CreateObject<Building>();
235
236 building->SetBoundaries(
237 Box(buildingIdX * (buildingSizeX + streetWidth),
238 buildingIdX * (buildingSizeX + streetWidth) + buildingSizeX,
239 buildingIdY * (buildingSizeY + streetWidth),
240 buildingIdY * (buildingSizeY + streetWidth) + buildingSizeY,
241 0.0,
242 buildingHeight));
243 building->SetNRoomsX(1);
244 building->SetNRoomsY(1);
245 building->SetNFloors(1);
246 buildingVector.push_back(building);
247 }
248 }
249
250 // set the mobility model
251 double vTx = vScatt;
252 double vRx = vScatt / 2;
255 Time nextWaypoint;
256 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
257 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 1.0, 1.5)));
258 nextWaypoint += Seconds((maxAxisY - streetWidth) / 2 / vTx);
259 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
260 Waypoint(nextWaypoint,
261 Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY / 2 - streetWidth / 2, 1.5)));
262 nextWaypoint += Seconds((maxAxisX - streetWidth) / 2 / vTx);
263 txMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
264 Waypoint(nextWaypoint, Vector(0.0, maxAxisY / 2 - streetWidth / 2, 1.5)));
265 nextWaypoint = Seconds(0);
266 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
267 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, 0.0, 1.5)));
268 nextWaypoint += Seconds(maxAxisY / vRx);
269 rxMob->GetObject<WaypointMobilityModel>()->AddWaypoint(
270 Waypoint(nextWaypoint, Vector(maxAxisX / 2 - streetWidth / 2, maxAxisY, 1.5)));
271
272 nodes.Get(0)->AggregateObject(txMob);
273 nodes.Get(1)->AggregateObject(rxMob);
274
275 // create the channel condition model
277
278 // create the propagation loss model
280 }
281 else if (scenario == "V2V-Highway")
282 {
283 // Two vehicles are travelling one behid the other with constant velocity
284 // along the y axis. The distance between the two vehicles is 20 meters.
285
286 // 3GPP defines that the maximum speed in urban scenario is 140 km/h
287 vScatt = 140 / 3.6;
288 double vTx = vScatt;
289 double vRx = vScatt / 2;
290
293 txMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 20.0, 1.5));
294 txMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vTx, 0.0));
295 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetPosition(Vector(300.0, 0.0, 1.5));
296 rxMob->GetObject<ConstantVelocityMobilityModel>()->SetVelocity(Vector(0.0, vRx, 0.0));
297
298 nodes.Get(0)->AggregateObject(txMob);
299 nodes.Get(1)->AggregateObject(rxMob);
300
301 // create the channel condition model
303
304 // create the propagation loss model
306 }
307 else
308 {
309 NS_FATAL_ERROR("Unknown scenario");
310 }
311
312 m_condModel->SetAttribute("UpdatePeriod", TimeValue(MilliSeconds(100)));
313
314 m_propagationLossModel->SetAttribute("Frequency", DoubleValue(frequency));
315 m_propagationLossModel->SetAttribute("ShadowingEnabled", BooleanValue(false));
316 m_propagationLossModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
317
318 // create the channel model
320 channelModel->SetAttribute("Scenario", StringValue(scenario));
321 channelModel->SetAttribute("Frequency", DoubleValue(frequency));
322 channelModel->SetAttribute("ChannelConditionModel", PointerValue(m_condModel));
323 channelModel->SetAttribute("vScatt", DoubleValue(vScatt));
324
325 // create the spectrum propagation loss model
327 "ChannelModel",
328 PointerValue(channelModel));
329
331
332 // set the beamforming vectors
333 DoBeamforming(txDev, txAntenna, rxDev);
334 DoBeamforming(rxDev, rxAntenna, txDev);
335
336 // create the tx power spectral density
337 Bands rbs;
338 double freqSubBand = frequency;
339 for (uint32_t n = 0; n < numRb; ++n)
340 {
341 BandInfo rb;
342 rb.fl = freqSubBand;
343 freqSubBand += subCarrierSpacing / 2;
344 rb.fc = freqSubBand;
345 freqSubBand += subCarrierSpacing / 2;
346 rb.fh = freqSubBand;
347 rbs.push_back(rb);
348 }
349 Ptr<SpectrumModel> spectrumModel = Create<SpectrumModel>(rbs);
350 Ptr<SpectrumValue> txPsd = Create<SpectrumValue>(spectrumModel);
352 double txPow_w = std::pow(10., (txPow_dbm - 30) / 10);
353 double txPowDens = (txPow_w / (numRb * subCarrierSpacing));
354 (*txPsd) = txPowDens;
355 txParams->psd = txPsd->Copy();
356
357 for (int i = 0; i < simTime / timeRes; i++)
358 {
359 ComputeSnrParams params{txMob, rxMob, txParams->Copy(), noiseFigure, txAntenna, rxAntenna};
360 Simulator::Schedule(timeRes * i, &ComputeSnr, params);
361 }
362
363 // initialize the output file
364 std::ofstream f;
365 f.open("example-output.txt", std::ios::out);
366 f << "Time[s] TxPosX[m] TxPosY[m] RxPosX[m] RxPosY[m] ChannelState SNR[dB] Pathloss[dB]"
367 << std::endl;
368 f.close();
369
370 // print the list of buildings to file
372
375 return 0;
376}
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 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:561
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:96
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:394
AttributeValue implementation for Time.
Definition nstime.h:1456
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:439
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
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 log component
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