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