merge
This commit is contained in:
98
src/propagation/examples/jakes-propagation-model-example.cc
Normal file
98
src/propagation/examples/jakes-propagation-model-example.cc
Normal file
@@ -0,0 +1,98 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Kirill Andreev <andreev@telum.ru>
|
||||
*/
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/jakes-propagation-loss-model.h"
|
||||
#include <vector>
|
||||
#include <math.h>
|
||||
|
||||
using namespace ns3;
|
||||
/**
|
||||
* \ingroup propagation
|
||||
* \brief Constructs a JakesPropagationlossModel and print the loss value as a function of time into std::cout.
|
||||
* Distribution and correlation statistics is compared woth a theoretical ones using R package (http://www.r-project.org/).
|
||||
* Scripts are presented within comments.
|
||||
*/
|
||||
class JakesPropagationExample
|
||||
{
|
||||
public:
|
||||
JakesPropagationExample ();
|
||||
~JakesPropagationExample ();
|
||||
private:
|
||||
Ptr<PropagationLossModel> m_loss;
|
||||
Ptr<MobilityModel> m_firstMobility;
|
||||
Ptr<MobilityModel> m_secondMobility;
|
||||
Time m_step;
|
||||
EventId m_nextEvent;
|
||||
void Next ();
|
||||
|
||||
};
|
||||
|
||||
JakesPropagationExample::JakesPropagationExample () :
|
||||
m_step (Seconds (0.0002)) //1/5000 part of the second
|
||||
{
|
||||
m_loss = CreateObject<JakesPropagationLossModel> ();
|
||||
m_firstMobility = CreateObject<ConstantPositionMobilityModel> ();
|
||||
m_secondMobility = CreateObject<ConstantPositionMobilityModel> ();
|
||||
m_firstMobility->SetPosition (Vector (0, 0, 0));
|
||||
m_secondMobility->SetPosition (Vector (10, 0, 0));
|
||||
m_nextEvent = Simulator::Schedule (m_step, &JakesPropagationExample::Next, this);
|
||||
}
|
||||
|
||||
JakesPropagationExample::~JakesPropagationExample ()
|
||||
{
|
||||
}
|
||||
|
||||
void JakesPropagationExample::Next ()
|
||||
{
|
||||
m_nextEvent = Simulator::Schedule (m_step, &JakesPropagationExample::Next, this);
|
||||
std::cout << Simulator::Now ().GetMilliSeconds () << " " << m_loss->CalcRxPower (0, m_firstMobility, m_secondMobility) << std::endl;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
Config::SetDefault ("ns3::JakesProcess::NumberOfOscillators", UintegerValue (100));
|
||||
CommandLine cmd;
|
||||
cmd.Parse (argc, argv);
|
||||
JakesPropagationExample example;
|
||||
Simulator::Stop (Seconds (1000));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
/*
|
||||
* R script for plotting a distribution:
|
||||
data<-read.table ("data")
|
||||
rayleigh<-(rnorm(1e6)^2+rnorm(1e6)^2)/2
|
||||
qqplot(10*log10(rayleigh), data$V2, main="QQ-plot for improved Jakes model", xlab="Reference Rayleigh distribution [power, dB]", ylab="Sum-of-sinusoids distribution [power, dB]", xlim=c(-45, 10), ylim=c(-45, 10))
|
||||
lines (c(-50, 50), c(-50, 50))
|
||||
abline (v=-50:50*2, h=-50:50*2, col="light grey")
|
||||
*/
|
||||
|
||||
/*
|
||||
* R script to plot autocorrelation function:
|
||||
# Read amplitude distribution:
|
||||
data<-10^(read.table ("data")$V2/20)
|
||||
x<-1:2000/10
|
||||
acf (data, lag.max=200, main="Autocorrelation function of the improved Jakes model", xlab="Time x200 microseconds ", ylab="Autocorrelation")
|
||||
# If we have a delta T = 1/5000 part of the second and doppler freq = 80 Hz
|
||||
lines (x, besselJ(x*80*2*pi/5000, 0)^2)
|
||||
abline (h=0:10/10, col="light grey")
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
@@ -249,7 +249,7 @@ int main (int argc, char *argv[])
|
||||
Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
|
||||
|
||||
// doppler frequency shift for 5.15 GHz at 100 km/h
|
||||
jakes->SetAttribute ("DopplerFreq", DoubleValue (477.9));
|
||||
Config::SetDefault ("ns3::JakesProcess::DopplerFrequencyHz", DoubleValue (477.9));
|
||||
|
||||
Gnuplot plot = TestDeterministicByTime (jakes, Seconds (0.001), Seconds (1.0));
|
||||
plot.SetTitle ("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 1 millisec resolution)");
|
||||
@@ -260,7 +260,7 @@ int main (int argc, char *argv[])
|
||||
Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
|
||||
|
||||
// doppler frequency shift for 5.15 GHz at 100 km/h
|
||||
jakes->SetAttribute ("DopplerFreq", DoubleValue (477.9));
|
||||
Config::SetDefault ("ns3::JakesProcess::DopplerFrequencyHz", DoubleValue (477.9));
|
||||
|
||||
Gnuplot plot = TestDeterministicByTime (jakes, Seconds (0.0001), Seconds (0.1));
|
||||
plot.SetTitle ("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 0.1 millisec resolution)");
|
||||
|
||||
@@ -8,4 +8,9 @@ def build(bld):
|
||||
['core', 'mobility', 'config-store', 'tools', 'propagation'])
|
||||
obj.source = 'main-propagation-loss.cc'
|
||||
|
||||
obj = bld.create_ns3_program('jakes-propagation-model-example',
|
||||
['core', 'propagation'])
|
||||
obj.source = 'jakes-propagation-model-example.cc'
|
||||
|
||||
|
||||
|
||||
|
||||
134
src/propagation/model/jakes-process.cc
Normal file
134
src/propagation/model/jakes-process.cc
Normal file
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Kirill Andreev <andreev@telum.ru>, Alexander Sofronov <sofronov@telum.ru>
|
||||
*/
|
||||
|
||||
#include "jakes-process.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/uinteger.h"
|
||||
|
||||
namespace ns3 {
|
||||
const double JakesProcess::PI = 3.14159265358979323846;
|
||||
|
||||
/// Represents a single oscillator
|
||||
JakesProcess::Oscillator::Oscillator (std::complex<double> amplitude, double initialPhase, double omega) :
|
||||
m_amplitude (amplitude),
|
||||
m_phase (initialPhase),
|
||||
m_omega (omega)
|
||||
{}
|
||||
|
||||
std::complex<double>
|
||||
JakesProcess::Oscillator::GetValueAt (Time at) const
|
||||
{
|
||||
return (m_amplitude * cos (at.GetSeconds () * m_omega + m_phase));
|
||||
}
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (JakesProcess);
|
||||
|
||||
TypeId
|
||||
JakesProcess::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::JakesProcess")
|
||||
.SetParent<Object> ()
|
||||
.AddConstructor<JakesProcess> ()
|
||||
.AddAttribute ("DopplerFrequencyHz", "Corresponding doppler frequency[Hz]",
|
||||
DoubleValue (80),
|
||||
MakeDoubleAccessor (&JakesProcess::SetDopplerFrequencyHz),
|
||||
MakeDoubleChecker<double> (0.0, 1e4))
|
||||
.AddAttribute ("NumberOfOscillators", "The number of oscillators",
|
||||
UintegerValue (20),
|
||||
MakeUintegerAccessor (&JakesProcess::SetNOscillators),
|
||||
MakeUintegerChecker<unsigned int> (4, 1000))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
void
|
||||
JakesProcess::SetNOscillators (unsigned int nOscillators)
|
||||
{
|
||||
m_nOscillators = nOscillators;
|
||||
if (m_omegaDopplerMax != 0)
|
||||
{
|
||||
ConstructOscillators ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JakesProcess::SetDopplerFrequencyHz (double dopplerFrequencyHz)
|
||||
{
|
||||
m_omegaDopplerMax = 2 * dopplerFrequencyHz * PI;
|
||||
if (m_nOscillators != 0)
|
||||
{
|
||||
ConstructOscillators ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JakesProcess::ConstructOscillators ()
|
||||
{
|
||||
// Initial phase is common for all oscillators:
|
||||
double phi = UniformVariable (-PI, PI).GetValue ();
|
||||
// Theta is common for all oscillatoer:
|
||||
double theta = UniformVariable (-PI, PI).GetValue ();
|
||||
for (unsigned int i = 0; i < m_nOscillators; i++)
|
||||
{
|
||||
unsigned int n = i + 1;
|
||||
/// 1. Rotation speed
|
||||
/// 1a. Initiate \f[ \alpha_n = \frac{2\pi n - \pi + \theta}{4M}, n=1,2, \ldots,M\f], n is oscillatorNumber, M is m_nOscillators
|
||||
double alpha = (2.0 * PI * n - PI + theta) / (4.0 * m_nOscillators);
|
||||
/// 1b. Initiate rotation speed:
|
||||
double omega = m_omegaDopplerMax * cos (alpha);
|
||||
/// 2. Initiate complex amplitude:
|
||||
double psi = UniformVariable (-PI, PI).GetValue ();
|
||||
std::complex<double> amplitude = std::complex<double> (cos (psi), sin (psi)) * 2.0 / sqrt (m_nOscillators);
|
||||
/// 3. Construct oscillator:
|
||||
m_oscillators.push_back (Oscillator (amplitude, phi, omega));
|
||||
}
|
||||
}
|
||||
|
||||
JakesProcess::JakesProcess () :
|
||||
m_omegaDopplerMax (0),
|
||||
m_nOscillators (0)
|
||||
{}
|
||||
|
||||
JakesProcess::~JakesProcess()
|
||||
{
|
||||
m_oscillators.clear ();
|
||||
}
|
||||
|
||||
std::complex<double>
|
||||
JakesProcess::GetComplexGain () const
|
||||
{
|
||||
std::complex<double> sumAplitude = std::complex<double> (0, 0);
|
||||
for (unsigned int i = 0; i < m_oscillators.size (); i++)
|
||||
{
|
||||
sumAplitude += m_oscillators[i].GetValueAt (Now ());
|
||||
}
|
||||
return sumAplitude;
|
||||
}
|
||||
|
||||
double
|
||||
JakesProcess::GetChannelGainDb () const
|
||||
{
|
||||
std::complex<double> complexGain = GetComplexGain ();
|
||||
return (10 * log10 ((pow (complexGain.real (), 2) + pow (complexGain.imag (), 2)) / 2));
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
92
src/propagation/model/jakes-process.h
Normal file
92
src/propagation/model/jakes-process.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Kirill Andreev <andreev@telum.ru>, Alexander Sofronov <sofronov@telum.ru>
|
||||
*/
|
||||
#ifndef DOPPLER_PROCESS_H
|
||||
#define DOPPLER_PROCESS_H
|
||||
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include <complex>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
/**
|
||||
* \ingroup fading
|
||||
*
|
||||
* \brief Implementation for a single path Stationary Jakes propagation loss model.
|
||||
*
|
||||
* The Jakes propagation loss model implemented here is
|
||||
* described in [1].
|
||||
*
|
||||
* We consider one transmitter - receiver pair and calculate
|
||||
* the complex coefficients for this case as follow:
|
||||
* \f[ X(t)=X_c(t) + j X_s(t)\f]
|
||||
* \f[ X_c(t) = \frac{2}{\sqrt{M}}\sum_{n=1}^{M}\cos(\psi_n)\cos(\omega_d t\cos(\alpha_n)+\phi_n)\f]
|
||||
* \f[ X_s(t) = \frac{2}{\sqrt{M}}\sum_{n=1}^{M}\sin(\psi_n)\cos(\omega_d t\cos(\alpha_n)+\phi_n)\f]
|
||||
* with
|
||||
* \f[ \alpha_n = \frac{2\pi n - \pi + \theta}{4M}, n=1,2, \ldots,M\f]
|
||||
* where
|
||||
*\f$\theta\f$, \f$\phi\f$, and \f$\psi_n\f$ are statically independent and uniformly distributed over \f$[-\pi, \pi)\f$ for all \f$n\f$.
|
||||
*
|
||||
*
|
||||
* [1] Y. R. Zheng and C. Xiao, "Simulation Models With Correct
|
||||
* Statistical Properties for Rayleigh Fading Channel", IEEE
|
||||
* Trans. on Communications, Vol. 51, pp 920-928, June 2003
|
||||
*/
|
||||
class JakesProcess : public Object
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
JakesProcess ();
|
||||
virtual ~JakesProcess();
|
||||
std::complex<double> GetComplexGain () const;
|
||||
/// Get Channel gain [dB]
|
||||
double GetChannelGainDb () const;
|
||||
private:
|
||||
/// Represents a single oscillator
|
||||
struct Oscillator
|
||||
{
|
||||
/// Initiate oscillator with complex amplitude, initial phase and rotation speed
|
||||
Oscillator (std::complex<double> amplitude, double initialPhase, double omega);
|
||||
// Get the complex amplitude at moment \param t
|
||||
std::complex<double> GetValueAt (Time t) const;
|
||||
/// Complex number \f[Re=\cos(\psi_n), Im = i\sin(\psi_n)]
|
||||
std::complex<double> m_amplitude;
|
||||
/// Phase \f[\phi_n] of the oscillator
|
||||
double m_phase;
|
||||
/// Rotation speed of the oscillator \f[\omega_d \cos(\alpha_n)]
|
||||
double m_omega;
|
||||
};
|
||||
/// PI Constant
|
||||
static const double PI;
|
||||
private:
|
||||
void SetNOscillators (unsigned int nOscillators);
|
||||
void SetDopplerFrequencyHz (double dopplerFrequencyHz);
|
||||
void ConstructOscillators ();
|
||||
private:
|
||||
/// Vector of oscillators:
|
||||
std::vector<Oscillator> m_oscillators;
|
||||
///\name Attributes:
|
||||
///\{
|
||||
double m_omegaDopplerMax;
|
||||
unsigned int m_nOscillators;
|
||||
///\}
|
||||
};
|
||||
} // namespace ns3
|
||||
#endif // DOPPLER_PROCESS_H
|
||||
@@ -1,9 +1,9 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
@@ -15,246 +15,37 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Federico Maguolo <maguolof@dei.unipd.it>
|
||||
* Author: Kirill Andreev <andreev@telum.ru>
|
||||
*/
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/mobility-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include "jakes-propagation-loss-model.h"
|
||||
#include <math.h>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("Jakes");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
NS_OBJECT_ENSURE_REGISTERED (JakesPropagationLossModel);
|
||||
|
||||
class JakesPropagationLossModel::PathCoefficients
|
||||
{
|
||||
public:
|
||||
PathCoefficients (Ptr<const JakesPropagationLossModel> jakes,
|
||||
Ptr<MobilityModel> receiver,
|
||||
uint8_t nRays,
|
||||
uint8_t nOscillators);
|
||||
~PathCoefficients ();
|
||||
double GetLoss (Ptr<const JakesPropagationLossModel> jakes);
|
||||
Ptr<MobilityModel> GetReceiver (void);
|
||||
private:
|
||||
void DoConstruct (Ptr<const JakesPropagationLossModel> jakes);
|
||||
Ptr<MobilityModel> m_receiver;
|
||||
uint8_t m_nOscillators;
|
||||
uint8_t m_nRays;
|
||||
double **m_phases;
|
||||
Time m_lastUpdate;
|
||||
};
|
||||
JakesPropagationLossModel::JakesPropagationLossModel()
|
||||
{}
|
||||
|
||||
|
||||
JakesPropagationLossModel::PathCoefficients::PathCoefficients (Ptr<const JakesPropagationLossModel> jakes,
|
||||
Ptr<MobilityModel> receiver,
|
||||
uint8_t nRays,
|
||||
uint8_t nOscillators)
|
||||
: m_receiver (receiver),
|
||||
m_nOscillators (nOscillators),
|
||||
m_nRays (nRays)
|
||||
{
|
||||
DoConstruct (jakes);
|
||||
}
|
||||
|
||||
JakesPropagationLossModel::PathCoefficients::~PathCoefficients ()
|
||||
{
|
||||
for (uint8_t i = 0; i < m_nRays; i++)
|
||||
{
|
||||
delete [] m_phases[i];
|
||||
}
|
||||
delete [] m_phases;
|
||||
}
|
||||
|
||||
void
|
||||
JakesPropagationLossModel::PathCoefficients::DoConstruct (Ptr<const JakesPropagationLossModel> jakes)
|
||||
{
|
||||
m_phases = new double*[m_nRays];
|
||||
for (uint8_t i = 0; i < m_nRays; i++)
|
||||
{
|
||||
m_phases[i] = new double[m_nOscillators + 1];
|
||||
for (uint8_t j = 0; j <= m_nOscillators; j++)
|
||||
{
|
||||
m_phases[i][j] = 2.0 * JakesPropagationLossModel::PI * jakes->m_variable.GetValue ();
|
||||
}
|
||||
}
|
||||
m_lastUpdate = Simulator::Now ();
|
||||
}
|
||||
|
||||
Ptr<MobilityModel>
|
||||
JakesPropagationLossModel::PathCoefficients::GetReceiver ()
|
||||
{
|
||||
return m_receiver;
|
||||
}
|
||||
|
||||
double
|
||||
JakesPropagationLossModel::PathCoefficients::GetLoss (Ptr<const JakesPropagationLossModel> jakes)
|
||||
{
|
||||
uint16_t N = 4 * m_nOscillators + 2;
|
||||
Time interval = Simulator::Now () - m_lastUpdate;
|
||||
ComplexNumber coef= { 0.0, 0.0};
|
||||
ComplexNumber fading;
|
||||
double norm = 0.0;
|
||||
for (uint8_t i = 0; i < m_nRays; i++)
|
||||
{
|
||||
fading.real = 0.0;
|
||||
fading.imag = 0.0;
|
||||
for (uint8_t j = 0; j <= m_nOscillators; j++)
|
||||
{
|
||||
m_phases[i][j] += 2.0 * JakesPropagationLossModel::PI *
|
||||
cos (2.0 * JakesPropagationLossModel::PI * j / N) * jakes->m_fd * interval.GetSeconds ();
|
||||
m_phases[i][j] -= 2.0 * JakesPropagationLossModel::PI *
|
||||
floor (m_phases[i][j] / 2.0 / JakesPropagationLossModel::PI);
|
||||
fading.real += jakes->m_amp[j].real * cos (m_phases[i][j]);
|
||||
fading.imag += jakes->m_amp[j].imag * cos (m_phases[i][j]);
|
||||
norm += sqrt (pow (jakes->m_amp[j].real, 2) + pow (jakes->m_amp[j].imag, 2));
|
||||
}
|
||||
coef.real += fading.real;
|
||||
coef.imag += fading.imag;
|
||||
}
|
||||
m_lastUpdate = Simulator::Now ();
|
||||
double k = sqrt (pow (coef.real, 2) + pow (coef.imag, 2)) / norm;
|
||||
NS_LOG_DEBUG ("Jakes coef "<< k << " (" << 10 * log10 (k) << "dB)");
|
||||
return 10 * log10 (k);
|
||||
}
|
||||
|
||||
const double JakesPropagationLossModel::PI = 3.14159265358979323846;
|
||||
JakesPropagationLossModel::~JakesPropagationLossModel()
|
||||
{}
|
||||
|
||||
TypeId
|
||||
JakesPropagationLossModel::GetTypeId (void)
|
||||
JakesPropagationLossModel::GetTypeId ()
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::JakesPropagationLossModel")
|
||||
.SetParent<PropagationLossModel> ()
|
||||
.AddConstructor<JakesPropagationLossModel> ()
|
||||
.AddAttribute ("NumberOfRaysPerPath",
|
||||
"The number of rays to use by default for compute the fading coeficent for a given path (default is 1)",
|
||||
UintegerValue (1),
|
||||
MakeUintegerAccessor (&JakesPropagationLossModel::SetNRays,
|
||||
&JakesPropagationLossModel::GetNRays),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
.AddAttribute ("NumberOfOscillatorsPerRay",
|
||||
"The number of oscillators to use by default for compute the coeficent for a given ray of a given "
|
||||
"path (default is 4)",
|
||||
UintegerValue (4),
|
||||
MakeUintegerAccessor (&JakesPropagationLossModel::SetNOscillators,
|
||||
&JakesPropagationLossModel::GetNOscillators),
|
||||
MakeUintegerChecker<uint8_t> ())
|
||||
.AddAttribute ("DopplerFreq",
|
||||
"The doppler frequency in Hz (f_d = v / lambda = v * f / c), the default is 0)",
|
||||
DoubleValue (0.0),
|
||||
MakeDoubleAccessor (&JakesPropagationLossModel::m_fd),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("Distribution",
|
||||
"The distribution to choose the initial phases.",
|
||||
RandomVariableValue (ConstantVariable (1.0)),
|
||||
MakeRandomVariableAccessor (&JakesPropagationLossModel::m_variable),
|
||||
MakeRandomVariableChecker ())
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
JakesPropagationLossModel::JakesPropagationLossModel ()
|
||||
: m_amp (0),
|
||||
m_nRays (0),
|
||||
m_nOscillators (0)
|
||||
{
|
||||
}
|
||||
|
||||
JakesPropagationLossModel::~JakesPropagationLossModel ()
|
||||
{
|
||||
delete [] m_amp;
|
||||
for (PathsList::reverse_iterator i = m_paths.rbegin (); i != m_paths.rend (); i++)
|
||||
{
|
||||
PathsSet *ps = *i;
|
||||
for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++)
|
||||
{
|
||||
PathCoefficients *pc = *r;
|
||||
delete pc;
|
||||
}
|
||||
ps->sender = 0;
|
||||
ps->receivers.clear ();
|
||||
delete ps;
|
||||
}
|
||||
m_paths.clear ();
|
||||
}
|
||||
|
||||
void
|
||||
JakesPropagationLossModel::SetNRays (uint8_t nRays)
|
||||
{
|
||||
m_nRays = nRays;
|
||||
}
|
||||
|
||||
void
|
||||
JakesPropagationLossModel::SetNOscillators (uint8_t nOscillators)
|
||||
{
|
||||
m_nOscillators = nOscillators;
|
||||
delete [] m_amp;
|
||||
uint16_t N = 4 * m_nOscillators + 2;
|
||||
m_amp = new ComplexNumber[m_nOscillators + 1];
|
||||
m_amp[0].real = 2.0 * sqrt (2.0 / N) * cos (PI / 4.0);
|
||||
m_amp[0].imag = 2.0 * sqrt (2.0 / N) * sin (PI / 4.0);
|
||||
for (uint8_t i = 1; i <= m_nOscillators; i++)
|
||||
{
|
||||
double beta = PI * (double)i / m_nOscillators;
|
||||
m_amp[i].real = 4.0 * cos (beta) / sqrt (N);
|
||||
m_amp[i].imag = 4.0 * sin (beta) / sqrt (N);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
JakesPropagationLossModel::GetNRays (void) const
|
||||
{
|
||||
return m_nRays;
|
||||
}
|
||||
uint8_t
|
||||
JakesPropagationLossModel::GetNOscillators (void) const
|
||||
{
|
||||
return m_nOscillators;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
double
|
||||
JakesPropagationLossModel::DoCalcRxPower (double txPowerDbm,
|
||||
Ptr<MobilityModel> a,
|
||||
Ptr<MobilityModel> b) const
|
||||
{
|
||||
PathsList::iterator i = m_paths.end ();
|
||||
while (i != m_paths.begin ())
|
||||
{
|
||||
i--;
|
||||
PathsSet *ps = *i;
|
||||
if (ps->sender == a)
|
||||
{
|
||||
m_paths.erase (i);
|
||||
m_paths.push_back (ps);
|
||||
for (DestinationList::iterator r = ps->receivers.begin (); r != ps->receivers.end (); r++)
|
||||
{
|
||||
PathCoefficients *pc = *r;
|
||||
if (pc->GetReceiver () == b)
|
||||
{
|
||||
ps->receivers.erase (r);
|
||||
ps->receivers.push_back (pc);
|
||||
return txPowerDbm + pc->GetLoss (this);
|
||||
}
|
||||
}
|
||||
PathCoefficients *pc = new PathCoefficients (this, b, m_nRays, m_nOscillators);
|
||||
ps->receivers.push_back (pc);
|
||||
return txPowerDbm + pc->GetLoss (this);
|
||||
}
|
||||
}
|
||||
PathsSet *ps = new PathsSet;
|
||||
ps->sender = a;
|
||||
PathCoefficients *pc = new PathCoefficients (this, b, m_nRays, m_nOscillators);
|
||||
ps->receivers.push_back (pc);
|
||||
m_paths.push_back (ps);
|
||||
return txPowerDbm + pc->GetLoss (this);
|
||||
return txPowerDbm + m_propagationCache.GetPathData (a, b, 0 /**Spectrum model uid is not used in PropagationLossModel*/)->GetChannelGainDb ();
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2005,2006,2007 INRIA
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
@@ -15,125 +15,41 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Federico Maguolo <maguolof@dei.unipd.it>
|
||||
* Author: Kirill Andreev <andreev@telum.ru>
|
||||
*/
|
||||
#ifndef PROPAGATION_JAKES_MODEL_H
|
||||
#define PROPAGATION_JAKES_MODEL_H
|
||||
|
||||
#include "ns3/nstime.h"
|
||||
#include "propagation-loss-model.h"
|
||||
|
||||
namespace ns3 {
|
||||
#ifndef JAKES_STATIONARY_LOSS_MODEL_H
|
||||
#define JAKES_STATIONARY_LOSS_MODEL_H
|
||||
|
||||
#include "ns3/propagation-loss-model.h"
|
||||
#include "ns3/propagation-cache.h"
|
||||
#include "ns3/jakes-process.h"
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
/**
|
||||
* \ingroup propagation
|
||||
*
|
||||
* \brief a Jakes propagation loss model
|
||||
*
|
||||
* The Jakes propagation loss model implemented here is
|
||||
* described in [1].
|
||||
*
|
||||
*
|
||||
* We call path the set of rays that depart from a given
|
||||
* transmitter and arrive to a given receiver. For each ray
|
||||
* The complex coefficient is compute as follow:
|
||||
* \f[ u(t)=u_c(t) + j u_s(t)\f]
|
||||
* \f[ u_c(t) = \frac{2}{\sqrt{N}}\sum_{n=0}^{M}a_n\cos(\omega_n t+\phi_n)\f]
|
||||
* \f[ u_s(t) = \frac{2}{\sqrt{N}}\sum_{n=0}^{M}b_n\cos(\omega_n t+\phi_n)\f]
|
||||
* where
|
||||
* \f[ a_n=\left \{ \begin{array}{ll}
|
||||
* \sqrt{2}\cos\beta_0 & n=0 \\
|
||||
* 2\cos\beta_n & n=1,2,\ldots,M
|
||||
* \end{array}
|
||||
* \right .\f]
|
||||
* \f[ b_n=\left \{ \begin{array}{ll}
|
||||
* \sqrt{2}\sin\beta_0 & n=0 \\
|
||||
* 2\sin\beta_n & n=1,2,\ldots,M
|
||||
* \end{array}
|
||||
* \right .\f]
|
||||
* \f[ \beta_n=\left \{ \begin{array}{ll}
|
||||
* \frac{\pi}{4} & n=0 \\
|
||||
* \frac{\pi n}{M} & n=1,2,\ldots,M
|
||||
* \end{array}
|
||||
* \right .\f]
|
||||
* \f[ \omega_n=\left \{ \begin{array}{ll}
|
||||
* 2\pi f_d & n=0 \\
|
||||
* 2\pi f_d \cos\frac{2\pi n}{N} & n=1,2,\ldots,M
|
||||
* \end{array}
|
||||
* \right .\f]
|
||||
*
|
||||
* The parameter \f$f_d\f$ is the doppler frequency and \f$N=4M+2\f$ where
|
||||
* \f$M\f$ is the number of oscillators per ray.
|
||||
*
|
||||
* The attenuation coefficent of the path is the magnitude of the sum of
|
||||
* all the ray coefficients. This attenuation coefficient could be greater than
|
||||
* \f$1\f$, hence it is divide by \f$ \frac{2N_r}{\sqrt{N}} \sum_{n+0}^{M}\sqrt{a_n^2 +b_n^2}\f$
|
||||
* where \f$N_r\f$ is the number of rays.
|
||||
*
|
||||
* The initail phases \f$\phi_i\f$ are random and they are choosen according
|
||||
* to a given distribution.
|
||||
*
|
||||
* [1] Y. R. Zheng and C. Xiao, "Simulation Models With Correct
|
||||
* Statistical Properties for Rayleigh Fading Channel", IEEE
|
||||
* Trans. on Communications, Vol. 51, pp 920-928, June 2003
|
||||
* \brief a jakes narrowband propagation model.
|
||||
* Symmetrical cache for JakesProcess
|
||||
*/
|
||||
|
||||
class JakesPropagationLossModel : public PropagationLossModel
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
static TypeId GetTypeId ();
|
||||
JakesPropagationLossModel ();
|
||||
virtual ~JakesPropagationLossModel ();
|
||||
|
||||
/**
|
||||
* \param nRays Number of rays per path
|
||||
*
|
||||
* Set the number of rays for each path
|
||||
*/
|
||||
void SetNRays (uint8_t nRays);
|
||||
/**
|
||||
* \param nOscillators Number of oscillators
|
||||
*
|
||||
* Set the number of oscillators to use to compute the ray coefficient
|
||||
*/
|
||||
void SetNOscillators (uint8_t nOscillators);
|
||||
|
||||
uint8_t GetNRays (void) const;
|
||||
uint8_t GetNOscillators (void) const;
|
||||
private:
|
||||
double DoCalcRxPower (double txPowerDbm,
|
||||
Ptr<MobilityModel> a,
|
||||
Ptr<MobilityModel> b) const;
|
||||
|
||||
private:
|
||||
JakesPropagationLossModel (const JakesPropagationLossModel &o);
|
||||
JakesPropagationLossModel & operator = (const JakesPropagationLossModel &o);
|
||||
void DoConstruct (void);
|
||||
virtual double DoCalcRxPower (double txPowerDbm,
|
||||
Ptr<MobilityModel> a,
|
||||
Ptr<MobilityModel> b) const;
|
||||
|
||||
class PathCoefficients;
|
||||
struct ComplexNumber {
|
||||
double real;
|
||||
double imag;
|
||||
};
|
||||
friend class PathCoefficents;
|
||||
typedef std::vector<PathCoefficients *> DestinationList;
|
||||
struct PathsSet {
|
||||
Ptr<MobilityModel> sender;
|
||||
DestinationList receivers;
|
||||
};
|
||||
typedef std::vector<PathsSet *> PathsList;
|
||||
|
||||
|
||||
static const double PI;
|
||||
ComplexNumber* m_amp;
|
||||
RandomVariable m_variable;
|
||||
double m_fd;
|
||||
mutable PathsList m_paths;
|
||||
uint8_t m_nRays;
|
||||
uint8_t m_nOscillators;
|
||||
mutable PropagationCache<JakesProcess> m_propagationCache;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* PROPAGATION_JAKES_MODEL_H */
|
||||
|
||||
#endif /* JAKES_STATIONARY_LOSS_MODEL_H */
|
||||
|
||||
|
||||
86
src/propagation/model/propagation-cache.h
Normal file
86
src/propagation/model/propagation-cache.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Telum (www.telum.ru)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Kirill Andreev <andreev@telum.ru>
|
||||
*/
|
||||
#ifndef PROPAGATION_CACHE_H_
|
||||
#define PROPAGATION_CACHE_H_
|
||||
|
||||
#include "ns3/mobility-model.h"
|
||||
#include <map>
|
||||
|
||||
namespace ns3
|
||||
{
|
||||
/**
|
||||
* \ingroup propagation
|
||||
* \brief Constructs a cache of objects, where each obect is responsible for a single propagation path loss calculations.
|
||||
* Propagation path a-->b and b-->a is the same thing. Propagation path is identified by
|
||||
* a couple of MobilityModels and a spectrum model UID
|
||||
*/
|
||||
template<class T>
|
||||
class PropagationCache
|
||||
{
|
||||
public:
|
||||
PropagationCache () {};
|
||||
~PropagationCache () {};
|
||||
Ptr<T> GetPathData (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b, uint32_t modelUid)
|
||||
{
|
||||
PropagationPathIdentifier key = PropagationPathIdentifier (a, b, modelUid);
|
||||
typename PathCache::iterator it = m_pathCache.find (key);
|
||||
if (it == m_pathCache.end ())
|
||||
{
|
||||
Ptr<T> newPath = CreateObject<T> ();
|
||||
m_pathCache.insert (std::make_pair (key, newPath));
|
||||
return newPath;
|
||||
}
|
||||
return it->second;
|
||||
};
|
||||
private:
|
||||
/// Each path is identified by
|
||||
struct PropagationPathIdentifier
|
||||
{
|
||||
PropagationPathIdentifier (Ptr<const MobilityModel> a, Ptr<const MobilityModel> b, uint32_t modelUid) :
|
||||
m_srcMobility (a), m_dstMobility (b), m_spectrumModelUid (modelUid)
|
||||
{};
|
||||
Ptr<const MobilityModel> m_srcMobility;
|
||||
Ptr<const MobilityModel> m_dstMobility;
|
||||
uint32_t m_spectrumModelUid;
|
||||
bool operator < (const PropagationPathIdentifier & other) const
|
||||
{
|
||||
if (m_spectrumModelUid != other.m_spectrumModelUid)
|
||||
{
|
||||
return m_spectrumModelUid < other.m_spectrumModelUid;
|
||||
}
|
||||
/// Links are supposed to be symmetrical!
|
||||
if (std::min (m_dstMobility, m_srcMobility) != std::min (other.m_dstMobility, other.m_srcMobility))
|
||||
{
|
||||
return std::min (m_dstMobility, m_srcMobility) < std::min (other.m_dstMobility, other.m_srcMobility);
|
||||
}
|
||||
if (std::max (m_dstMobility, m_srcMobility) != std::max (other.m_dstMobility, other.m_srcMobility))
|
||||
{
|
||||
return std::max (m_dstMobility, m_srcMobility) < std::max (other.m_dstMobility, other.m_srcMobility);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
typedef std::map<PropagationPathIdentifier, Ptr<T> > PathCache;
|
||||
private:
|
||||
PathCache m_pathCache;
|
||||
};
|
||||
} // namespace ns3
|
||||
|
||||
#endif // PROPAGATION_CACHE_H_
|
||||
@@ -7,6 +7,7 @@ def build(bld):
|
||||
'model/propagation-delay-model.cc',
|
||||
'model/propagation-loss-model.cc',
|
||||
'model/jakes-propagation-loss-model.cc',
|
||||
'model/jakes-process.cc',
|
||||
'model/cost231-propagation-loss-model.cc',
|
||||
'model/okumura-hata-propagation-loss-model.cc',
|
||||
'model/itu-r-1411-los-propagation-loss-model.cc',
|
||||
@@ -29,6 +30,8 @@ def build(bld):
|
||||
'model/propagation-delay-model.h',
|
||||
'model/propagation-loss-model.h',
|
||||
'model/jakes-propagation-loss-model.h',
|
||||
'model/jakes-process.h',
|
||||
'model/propagation-cache.h',
|
||||
'model/cost231-propagation-loss-model.h',
|
||||
'model/propagation-environment.h',
|
||||
'model/okumura-hata-propagation-loss-model.h',
|
||||
|
||||
Reference in New Issue
Block a user