Skip to content

Commit

Permalink
Switch to CMake-based build system, introduce support for ns-3.38 (#6)
Browse files Browse the repository at this point in the history
* initial CMake setup

* fix channel params

* fix missing includes

* fix missing update of gen. time field
  • Loading branch information
pagmatt committed Apr 18, 2023
1 parent 5b283e4 commit 43df1ba
Show file tree
Hide file tree
Showing 13 changed files with 1,032 additions and 975 deletions.
27 changes: 27 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
check_include_file_cxx(stdint.h HAVE_STDINT_H)
if(HAVE_STDINT_H)
add_definitions(-DHAVE_STDINT_H)
endif()

set(examples_as_tests_sources)
if(${ENABLE_EXAMPLES})
set(examples_as_tests_sources
test/qd-channel-test-suite.cc
)
endif()

build_lib(
LIBNAME qd-channel
SOURCE_FILES
model/qd-channel-model.cc
model/qd-channel-utils.cc
HEADER_FILES
model/qd-channel-model.h
model/qd-channel-utils.h
LIBRARIES_TO_LINK
${libcore}
${libspectrum}
TEST_SOURCES test/qd-channel-test-suite.cc
${examples_as_tests_sources}
)

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ The example `qd-channel-model-example.cc` can be used as a starting point to und
### Prerequisites ###

To run simulations using this module, you will need to install ns-3, and clone
this repository inside the `contrib` directory.
this repository inside the `contrib` directory.
Required dependencies include git and a build environment.

Please check the [release page](https://github.com/signetlabdei/qd-channel/releases) for further information on the compatible versions of ns-3.
Expand Down
8 changes: 4 additions & 4 deletions doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ IMAGES_EPS = \

# rescale pdf figures as necessary

IMAGES_NOBUILD =
IMAGES_NOBUILD =
# IMAGES_NOBUILD = $(FIGURES)/fading_pedestrian.png \
IMAGES_BUILD = \
${IMAGES_DIA:.dia=.eps} \
${IMAGES_DIA:.dia=.png} \
${IMAGES_DIA:.dia=.pdf} \
${IMAGES_EPS:.eps=.png} \
${IMAGES_EPS:.eps=.pdf}
${IMAGES_EPS:.eps=.pdf}


IMAGES = $(IMAGES_NOBUILD) $(IMAGES_BUILD)
Expand All @@ -49,7 +49,7 @@ BUILDDIR = build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCE)

.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest

Expand Down Expand Up @@ -84,7 +84,7 @@ frag: pickle
pushd $(BUILDDIR)/frag && ../../pickle-to-xml.py ../pickle/index.fpickle > navigation.xml && popd
cp -r $(BUILDDIR)/pickle/_images $(BUILDDIR)/frag

html: $(IMAGES)
html: $(IMAGES)
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
Expand Down
2 changes: 1 addition & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@


# add page breaks in the pdf. Level 1 is for top-level sections, level 2 for subsections, and so on.
pdf_break_level = 4
pdf_break_level = 4


# -- Options for manual page output --------------------------------------------
Expand Down
9 changes: 9 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
build_lib_example(
NAME qd-channel-model-example
SOURCE_FILES qd-channel-model-example.cc
LIBRARIES_TO_LINK
${libqd-channel}
${libspectrum}
${liblte}
)

267 changes: 144 additions & 123 deletions examples/qd-channel-model-example.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,27 @@
* Each node hosts a SimpleNetDevice and has a 2x2 antenna array.
*/

#include <fstream>
#include "ns3/constant-position-mobility-model.h"
#include "ns3/core-module.h"
#include "ns3/qd-channel-model.h"
#include "ns3/uniform-planar-array.h"
#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
#include "ns3/simple-net-device.h"
#include "ns3/node-container.h"
#include "ns3/constant-position-mobility-model.h"
#include "ns3/lte-spectrum-value-helper.h"
#include "ns3/qd-channel-model.h"
#include "ns3/qd-channel-utils.h"
#include "ns3/simple-net-device.h"
#include "ns3/three-gpp-spectrum-propagation-loss-model.h"
#include "ns3/uniform-planar-array.h"
#include <ns3/lte-spectrum-value-helper.h>
#include <ns3/spectrum-signal-parameters.h>

NS_LOG_COMPONENT_DEFINE ("QdChannelModelExample");
#include <fstream>

NS_LOG_COMPONENT_DEFINE("QdChannelModelExample");

using namespace ns3;

// Simulation parameters
double txPow = 20.0; // Tx power in dBm
double txPow = 20.0; // Tx power in dBm
double noiseFigure = 9.0; // Noise figure in dB
uint32_t timeRes = 5; // Time resolution in milliseconds
uint32_t timeRes = 5; // Time resolution in milliseconds

// main variables
Ptr<QdChannelModel> qdChannel;
Expand All @@ -59,135 +61,154 @@ Ptr<ThreeGppSpectrumPropagationLossModel> spectrumLossModel;
* \param rxDevice the device towards which point the beam
* \param rxAntenna the antenna object associated to rxDevice
*/
static void DoBeamforming (Ptr<NetDevice> txDevice, Ptr<PhasedArrayModel> txAntenna,
Ptr<NetDevice> rxDevice, Ptr<PhasedArrayModel> rxAntenna);
static void DoBeamforming(Ptr<NetDevice> txDevice,
Ptr<PhasedArrayModel> txAntenna,
Ptr<NetDevice> rxDevice,
Ptr<PhasedArrayModel> rxAntenna);
/*
* Compute the average SNR, print it to both terminal and file
*/
static void ComputeSnr ();
static void ComputeSnr();

int
main (int argc, char *argv[])
main(int argc, char* argv[])
{
std::string qdFilesPath = "contrib/qd-channel/model/QD/"; // The path of the folder with the QD scenarios
std::string scenario = "Indoor1"; // The name of the scenario

RngSeedManager::SetSeed (1);
RngSeedManager::SetRun (1);

// Create the tx and rx nodes
NodeContainer nodes;
nodes.Create (2);
Ptr<Node> txNode = nodes.Get (0);
Ptr<Node> rxNode = nodes.Get (1);

// Create the tx and rx devices
Ptr<SimpleNetDevice> txDev = CreateObject<SimpleNetDevice> ();
Ptr<SimpleNetDevice> rxDev = CreateObject<SimpleNetDevice> ();

// Associate the nodes and the devices
txNode->AddDevice (txDev);
txDev->SetNode (txNode);
rxNode->AddDevice (rxDev);
rxDev->SetNode (rxNode);

// Create the tx and rx mobility models
// Set the positions to be equal to the initial positions of the nodes in the ray tracer
rxMob = CreateObject<ConstantPositionMobilityModel> ();
rxMob->SetPosition (Vector (5, 0.1, 1.5));
txMob = CreateObject<ConstantPositionMobilityModel> ();
txMob->SetPosition (Vector (5, 0.1, 2.9));

// Assign the mobility models to the nodes
txNode->AggregateObject (txMob);
rxNode->AggregateObject (rxMob);

// Create the QdChannelModel
qdChannel = CreateObject<QdChannelModel> (qdFilesPath, scenario);
Time simTime = qdChannel->GetQdSimTime ();

// Create the spectrum propagation loss model
spectrumLossModel = CreateObjectWithAttributes<ThreeGppSpectrumPropagationLossModel> ("ChannelModel", PointerValue (qdChannel));

// Create the antenna objects and set their dimensions
txAntenna = CreateObjectWithAttributes<UniformPlanarArray> ("NumColumns", UintegerValue (2),
"NumRows", UintegerValue (2));
txNode->AggregateObject (txAntenna);

rxAntenna = CreateObjectWithAttributes<UniformPlanarArray> ("NumColumns", UintegerValue (2),
"NumRows", UintegerValue (2));
rxNode->AggregateObject (rxAntenna);

// Initialize the devices in the ThreeGppSpectrumPropagationLossModel
spectrumLossModel->AddDevice (txDev, txAntenna);
spectrumLossModel->AddDevice (rxDev, rxAntenna);

// Compute and print SNR
Simulator::ScheduleNow (&ComputeSnr);

Simulator::Stop (simTime);
Simulator::Run ();
Simulator::Destroy ();
return 0;
std::string qdFilesPath =
"contrib/qd-channel/model/QD/"; // The path of the folder with the QD scenarios
std::string scenario = "Indoor1"; // The name of the scenario

RngSeedManager::SetSeed(1);
RngSeedManager::SetRun(1);

// Create the tx and rx nodes
NodeContainer nodes;
nodes.Create(2);
Ptr<Node> txNode = nodes.Get(0);
Ptr<Node> rxNode = nodes.Get(1);

// Create the tx and rx devices
Ptr<SimpleNetDevice> txDev = CreateObject<SimpleNetDevice>();
Ptr<SimpleNetDevice> rxDev = CreateObject<SimpleNetDevice>();

// Associate the nodes and the devices
txNode->AddDevice(txDev);
txDev->SetNode(txNode);
rxNode->AddDevice(rxDev);
rxDev->SetNode(rxNode);

// Create the tx and rx mobility models
// Set the positions to be equal to the initial positions of the nodes in the ray tracer
rxMob = CreateObject<ConstantPositionMobilityModel>();
rxMob->SetPosition(Vector(5, 0.1, 1.5));
txMob = CreateObject<ConstantPositionMobilityModel>();
txMob->SetPosition(Vector(5, 0.1, 2.9));

// Assign the mobility models to the nodes
txNode->AggregateObject(txMob);
rxNode->AggregateObject(rxMob);

// Create the QdChannelModel
qdChannel = CreateObject<QdChannelModel>(qdFilesPath, scenario);
Time simTime = qdChannel->GetQdSimTime();

// Create the spectrum propagation loss model
spectrumLossModel =
CreateObjectWithAttributes<ThreeGppSpectrumPropagationLossModel>("ChannelModel",
PointerValue(qdChannel));

// Create the antenna objects and set their dimensions
txAntenna = CreateObjectWithAttributes<UniformPlanarArray>("NumColumns",
UintegerValue(2),
"NumRows",
UintegerValue(2));
txNode->AggregateObject(txAntenna);

rxAntenna = CreateObjectWithAttributes<UniformPlanarArray>("NumColumns",
UintegerValue(2),
"NumRows",
UintegerValue(2));
rxNode->AggregateObject(rxAntenna);

// Initialize the devices in the ThreeGppSpectrumPropagationLossModel
// spectrumLossModel->AddDevice (txDev, txAntenna);
// spectrumLossModel->AddDevice (rxDev, rxAntenna);

// Compute and print SNR
Simulator::ScheduleNow(&ComputeSnr);

Simulator::Stop(simTime);
Simulator::Run();
Simulator::Destroy();
return 0;
}

/* UTILITIES */
static void
DoBeamforming (Ptr<NetDevice> txDevice, Ptr<PhasedArrayModel> txAntenna,
Ptr<NetDevice> rxDevice, Ptr<PhasedArrayModel> rxAntenna)
DoBeamforming(Ptr<NetDevice> txDevice,
Ptr<PhasedArrayModel> txAntenna,
Ptr<NetDevice> rxDevice,
Ptr<PhasedArrayModel> rxAntenna)
{
Ptr<MobilityModel> thisMob = txDevice->GetNode ()->GetObject<MobilityModel> ();
Ptr<MobilityModel> otherMob = rxDevice->GetNode ()->GetObject<MobilityModel> ();
Ptr<const MatrixBasedChannelModel::ChannelMatrix> channelMatrix =
qdChannel->GetChannel (thisMob, otherMob, txAntenna, rxAntenna);
Ptr<MobilityModel> thisMob = txDevice->GetNode()->GetObject<MobilityModel>();
Ptr<MobilityModel> otherMob = rxDevice->GetNode()->GetObject<MobilityModel>();
Ptr<const MatrixBasedChannelModel::ChannelMatrix> channelMatrix =
qdChannel->GetChannel(thisMob, otherMob, txAntenna, rxAntenna);

auto bfVectors = ComputeSvdBeamformingVectors (channelMatrix);
auto bfVectors = ComputeSvdBeamformingVectors(channelMatrix);

// store the antenna weights
txAntenna->SetBeamformingVector (std::get<0> (bfVectors));
rxAntenna->SetBeamformingVector (std::get<1> (bfVectors));
// store the antenna weights
txAntenna->SetBeamformingVector(std::get<0>(bfVectors));
rxAntenna->SetBeamformingVector(std::get<1>(bfVectors));
}

static void
ComputeSnr ()
ComputeSnr()
{
// Create the tx PSD using the LteSpectrumValueHelper
// 100 RBs corresponds to 18 MHz (1 RB = 180 kHz)
// EARFCN 100 corresponds to 2125.00 MHz
std::vector<int> activeRbs0 (100);
for (int i = 0; i < 100; i++)
// Create the tx PSD using the LteSpectrumValueHelper
// 100 RBs corresponds to 18 MHz (1 RB = 180 kHz)
// EARFCN 100 corresponds to 2125.00 MHz
std::vector<int> activeRbs0(100);
for (int i = 0; i < 100; i++)
{
activeRbs0[i] = i;
activeRbs0[i] = i;
}
Ptr<SpectrumValue> txPsd =
LteSpectrumValueHelper::CreateTxPowerSpectralDensity (2100, 100, txPow, activeRbs0);
Ptr<SpectrumValue> rxPsd = txPsd->Copy ();
NS_LOG_DEBUG ("Average tx power " << 10 * log10 (Sum (*txPsd) * 180e3) << " dB");

// Create the noise PSD
Ptr<SpectrumValue> noisePsd =
LteSpectrumValueHelper::CreateNoisePowerSpectralDensity (2100, 100, noiseFigure);
NS_LOG_DEBUG ("Average noise power " << 10 * log10 (Sum (*noisePsd) * 180e3) << " dB");

// compute beamforming vectors
Ptr<NetDevice> txDevice = txMob->GetObject<Node> ()->GetDevice (0);
Ptr<NetDevice> rxDevice = rxMob->GetObject<Node> ()->GetDevice (0);

DoBeamforming (txDevice, txAntenna, rxDevice, rxAntenna);

// Apply the fast fading and the beamforming gain
rxPsd = spectrumLossModel->CalcRxPowerSpectralDensity (rxPsd, txMob, rxMob);
NS_LOG_DEBUG ("Average rx power " << 10 * log10 (Sum (*rxPsd) * 180e3) << " dB");

// Compute the SNR
NS_LOG_DEBUG ("Average SNR " << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << " dB");

// Print the SNR and pathloss values in the snr-trace.txt file
std::ofstream f;
f.open ("snr-trace.txt", std::ios::out | std::ios::app);
NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << "\t" << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)));
f << Simulator::Now ().GetSeconds () << "\t" << 10 * log10 (Sum (*rxPsd) / Sum (*noisePsd)) << std::endl;
f.close ();

Simulator::Schedule (MilliSeconds (timeRes), &ComputeSnr);
}
Ptr<SpectrumValue> txPsd =
LteSpectrumValueHelper::CreateTxPowerSpectralDensity(2100, 100, txPow, activeRbs0);
Ptr<SpectrumValue> rxPsd = txPsd->Copy();
NS_LOG_DEBUG("Average tx power " << 10 * log10(Sum(*txPsd) * 180e3) << " dB");

// Create the noise PSD
Ptr<SpectrumValue> noisePsd =
LteSpectrumValueHelper::CreateNoisePowerSpectralDensity(2100, 100, noiseFigure);
NS_LOG_DEBUG("Average noise power " << 10 * log10(Sum(*noisePsd) * 180e3) << " dB");

// compute beamforming vectors
Ptr<NetDevice> txDevice = txMob->GetObject<Node>()->GetDevice(0);
Ptr<NetDevice> rxDevice = rxMob->GetObject<Node>()->GetDevice(0);

DoBeamforming(txDevice, txAntenna, rxDevice, rxAntenna);

// Apply the fast fading and the beamforming gain
Ptr<SpectrumSignalParameters> rxParameters = Create<SpectrumSignalParameters>();
rxParameters->psd = rxPsd;
rxPsd = spectrumLossModel->CalcRxPowerSpectralDensity(rxParameters,
txMob,
rxMob,
txAntenna,
rxAntenna);
NS_LOG_DEBUG("Average rx power " << 10 * log10(Sum(*rxPsd) * 180e3) << " dB");

// Compute the SNR
NS_LOG_DEBUG("Average SNR " << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)) << " dB");

// Print the SNR and pathloss values in the snr-trace.txt file
std::ofstream f;
f.open("snr-trace.txt", std::ios::out | std::ios::app);
NS_LOG_UNCOND(Simulator::Now().GetSeconds()
<< "\t" << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd)));
f << Simulator::Now().GetSeconds() << "\t" << 10 * log10(Sum(*rxPsd) / Sum(*noisePsd))
<< std::endl;
f.close();

Simulator::Schedule(MilliSeconds(timeRes), &ComputeSnr);
}
Loading

0 comments on commit 43df1ba

Please sign in to comment.