add BSM application and vanet-routing-compare example

This commit is contained in:
Scott Carpenter
2015-01-26 15:20:09 -08:00
parent a31a3245f2
commit 3e74003142
10 changed files with 5314 additions and 0 deletions

View File

@@ -270,4 +270,22 @@ MobilityHelper::AssignStreams (NodeContainer c, int64_t stream)
return (currentStream - stream);
}
double
MobilityHelper::GetDistanceSquaredBetween (Ptr<Node> n1, Ptr<Node> n2)
{
NS_LOG_FUNCTION_NOARGS ();
double distSq = 0.0;
Ptr<MobilityModel> rxPosition = n1->GetObject<MobilityModel> ();
NS_ASSERT (rxPosition != 0);
Ptr<MobilityModel> txPosition = n2->GetObject<MobilityModel> ();
NS_ASSERT (txPosition != 0);
double dist = rxPosition -> GetDistanceFrom (txPosition);
distSq = dist * dist;
return distSq;
}
} // namespace ns3

View File

@@ -260,6 +260,13 @@ public:
*/
int64_t AssignStreams (NodeContainer c, int64_t stream);
/**
* \param n1 node 1
* \param n2 node 2
* \return the distance (squared), in meters, between two nodes
*/
static double GetDistanceSquaredBetween (Ptr<Node> n1, Ptr<Node> n2);
private:
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,164 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#include "ns3/wave-bsm-helper.h"
#include "ns3/log.h"
NS_LOG_COMPONENT_DEFINE ("WaveBsmHelper");
namespace ns3 {
std::vector<int> WaveBsmHelper::nodesMoving;
WaveBsmHelper::WaveBsmHelper ()
: m_waveBsmStats ()
{
m_txSafetyRangesSq.resize (10, 0);
m_txSafetyRangesSq[0] = 50.0 * 50.0;
m_txSafetyRangesSq[1] = 100.0 * 100.0;
m_txSafetyRangesSq[2] = 200.0 * 200.0;
m_txSafetyRangesSq[3] = 300.0 * 300.0;
m_txSafetyRangesSq[4] = 400.0 * 400.0;
m_txSafetyRangesSq[5] = 500.0 * 500.0;
m_txSafetyRangesSq[6] = 600.0 * 600.0;
m_txSafetyRangesSq[7] = 800.0 * 800.0;
m_txSafetyRangesSq[8] = 1000.0 * 1000.0;
m_txSafetyRangesSq[9] = 1500.0 * 1500.0;
m_factory.SetTypeId ("ns3::BsmApplication");
}
void
WaveBsmHelper::SetAttribute (std::string name, const AttributeValue &value)
{
m_factory.Set (name, value);
}
ApplicationContainer
WaveBsmHelper::Install (Ptr<Node> node) const
{
return ApplicationContainer (InstallPriv (node));
}
ApplicationContainer
WaveBsmHelper::Install (Ipv4InterfaceContainer i) const
{
ApplicationContainer apps;
for (Ipv4InterfaceContainer::Iterator itr = i.Begin (); itr != i.End (); ++itr)
{
std::pair<Ptr<Ipv4>, uint32_t> interface = (*itr);
Ptr<Ipv4> pp = interface.first;
Ptr<Node> node = pp->GetObject<Node> ();
apps.Add (InstallPriv (node));
}
return apps;
}
Ptr<Application>
WaveBsmHelper::InstallPriv (Ptr<Node> node) const
{
Ptr<Application> app = m_factory.Create<Application> ();
node->AddApplication (app);
return app;
}
void
WaveBsmHelper::Install (Ipv4InterfaceContainer & i,
Time totalTime, // seconds
uint32_t wavePacketSize, // bytes
Time waveInterval, // seconds
double gpsAccuracyNs, // clock drift range in number of ns
std::vector <double> ranges, // m
int chAccessMode, // channel access mode
Time txMaxDelay) // max delay prior to transmit
{
int size = ranges.size ();
m_txSafetyRangesSq.clear ();
m_txSafetyRangesSq.resize (size, 0);
for (int index = 0; index < size; index++)
{
// stored as square of value, for optimization
m_txSafetyRangesSq[index] = ranges[index] * ranges[index];
}
// install a BsmApplication on each node
ApplicationContainer bsmApps = Install (i);
// start BSM app immediately (BsmApplication will
// delay transmission of first BSM by 1.0 seconds)
bsmApps.Start (Seconds (0));
bsmApps.Stop (totalTime);
// for each app, setup the app parameters
ApplicationContainer::Iterator aci;
int nodeId = 0;
for (aci = bsmApps.Begin (); aci != bsmApps.End (); ++aci)
{
Ptr<BsmApplication> bsmApp = DynamicCast<BsmApplication> (*aci);
bsmApp->Setup (i,
nodeId,
totalTime,
wavePacketSize,
waveInterval,
gpsAccuracyNs,
m_txSafetyRangesSq,
GetWaveBsmStats (),
&nodesMoving,
chAccessMode,
txMaxDelay);
nodeId++;
}
}
Ptr<WaveBsmStats>
WaveBsmHelper::GetWaveBsmStats ()
{
return &m_waveBsmStats;
}
int64_t
WaveBsmHelper::AssignStreams (NodeContainer c, int64_t stream)
{
int64_t currentStream = stream;
Ptr<Node> node;
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
node = (*i);
for (uint32_t j = 0; j < node->GetNApplications (); j++)
{
Ptr<BsmApplication> bsmApp = DynamicCast<BsmApplication> (node->GetApplication (j));
if (bsmApp)
{
currentStream += bsmApp->AssignStreams (currentStream);
}
}
}
return (currentStream - stream);
}
std::vector<int>&
WaveBsmHelper::GetNodesMoving ()
{
return nodesMoving;
}
} // namespace ns3

View File

@@ -0,0 +1,147 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#ifndef WAVE_BSM_HELPER_H
#define WAVE_BSM_HELPER_H
#include <vector>
#include "ns3/wave-bsm-stats.h"
#include "ns3/bsm-application.h"
#include "ns3/object-factory.h"
#include "ns3/application-container.h"
#include "ns3/nstime.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/mobility-model.h"
namespace ns3 {
/**
* \ingroup wave
* \brief The WaveBsmHelper class manages
* IEEE 1609 WAVE (Wireless Access in Vehicular Environments)
* Basic Safety Messages (BSMs) and uses the WaveBsmStats class
* to manage statistics about BSMs transmitted and received
* The BSM is a ~200-byte packet that is
* generally broadcast from every vehicle at a nominal rate of 10 Hz.
*/
class WaveBsmHelper
{
public:
/**
* \brief Constructor
* \return none
*/
WaveBsmHelper ();
/**
* Helper function used to set the underlying application attributes.
*
* \param name the name of the application attribute to set
* \param value the value of the application attribute to set
*/
void SetAttribute (std::string name, const AttributeValue &value);
/**
* Install an ns3::BsmApplication on each node of the input container
* configured with all the attributes set with SetAttribute.
*
* \param i Ipv4InterfaceContainer of the set of interfaces on which an BsmApplication
* will be installed on the nodes.
* \returns Container of Ptr to the applications installed.
*/
ApplicationContainer Install (Ipv4InterfaceContainer i) const;
/**
* Install an ns3::BsmApplication on the node configured with all the
* attributes set with SetAttribute.
*
* \param node The node on which an BsmApplication will be installed.
* \returns Container of Ptr to the applications installed.
*/
ApplicationContainer Install (Ptr<Node> node) const;
/**
* \brief Installs BSM generation on devices for nodes
* and their interfaces
* \param i IPv4 interface container
* \param totalTime total amount of time that BSM packets should be transmitted
* \param wavePacketSize the size, in bytes, of a WAVE BSM
* \param waveInterval the time, in seconds, between each WAVE BSM transmission,
* typically 10 Hz (0.1 second)
* \param gpsAccuracy the timing synchronization accuracy of GPS time, in seconds.
* GPS time-sync is ~40-100 ns. Universally synchronized time among all vehicles
* will result in all vehicles transmitting safety messages simultaneously, leading
* to excessive wireless collisions.
* \param range the expected transmission range, in m.
* \return none
*/
void Install (Ipv4InterfaceContainer & i,
Time totalTime, // seconds
uint32_t wavePacketSize, // bytes
Time waveInterval, // seconds
double gpsAccuracyNs, // clock drift range in number of ns
std::vector <double> ranges, // m
int chAccessMode, // channel access mode (0=continuous; 1=switching)
Time txMaxDelay); // max delay prior to transmit
/**
* \brief Returns the WaveBsmStats instance
* \return the WaveBsmStats instance
*/
Ptr<WaveBsmStats> GetWaveBsmStats ();
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
* have been assigned. The Install() method should have previously been
* called by the user.
*
* \param stream first stream index to use
* \param c NodeContainer of the set of nodes for which the BsmApplication
* should be modified to use a fixed stream
* \return the number of stream indices assigned by this helper
*/
int64_t AssignStreams (NodeContainer c, int64_t stream);
/**
* \brief Returns the list of moving nove indicators
* \return the list of moving node indicators
*/
static std::vector<int>& GetNodesMoving ();
private:
/**
* Install an ns3::BsmApplication on the node
*
* \param node The node on which an BsmApplication will be installed.
* \returns Ptr to the application installed.
*/
Ptr<Application> InstallPriv (Ptr<Node> node) const;
ObjectFactory m_factory; //!< Object factory.
WaveBsmStats m_waveBsmStats;
// tx safety range squared, for optimization
std::vector <double> m_txSafetyRangesSq;
static std::vector<int> nodesMoving;
};
} // namespace ns3
#endif /* WAVE_BSM_HELPER_H*/

View File

@@ -0,0 +1,190 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#include "ns3/wave-bsm-stats.h"
#include "ns3/integer.h"
#include "ns3/log.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("WaveBsmStats");
WaveBsmStats::WaveBsmStats ()
: m_wavePktSendCount (0),
m_waveByteSendCount (0),
m_wavePktReceiveCount (0),
m_log (0)
{
m_wavePktExpectedReceiveCounts.resize (10, 0);
m_wavePktInCoverageReceiveCounts.resize (10, 0);
m_waveTotalPktExpectedReceiveCounts.resize (10, 0);
m_waveTotalPktInCoverageReceiveCounts.resize (10, 0);
}
void
WaveBsmStats::IncTxPktCount ()
{
m_wavePktSendCount++;
}
int
WaveBsmStats::GetTxPktCount ()
{
return m_wavePktSendCount;
}
void
WaveBsmStats::IncExpectedRxPktCount (int index)
{
m_wavePktExpectedReceiveCounts[index - 1]++;
m_waveTotalPktExpectedReceiveCounts[index - 1]++;
}
void
WaveBsmStats::IncRxPktCount ()
{
m_wavePktReceiveCount++;
}
void
WaveBsmStats::IncRxPktInRangeCount (int index)
{
m_wavePktInCoverageReceiveCounts[index - 1]++;
m_waveTotalPktInCoverageReceiveCounts[index - 1]++;
}
int
WaveBsmStats::GetRxPktCount ()
{
return m_wavePktReceiveCount;
}
int
WaveBsmStats::GetExpectedRxPktCount (int index)
{
return m_wavePktExpectedReceiveCounts[index - 1];
}
int
WaveBsmStats::GetRxPktInRangeCount (int index)
{
return m_wavePktInCoverageReceiveCounts[index - 1];
}
void
WaveBsmStats::SetTxPktCount (int count)
{
m_wavePktSendCount = count;
}
void
WaveBsmStats::SetRxPktCount (int count)
{
m_wavePktReceiveCount = count;
}
void
WaveBsmStats::IncTxByteCount (int bytes)
{
m_waveByteSendCount += bytes;
}
int
WaveBsmStats::GetTxByteCount ()
{
return m_waveByteSendCount;
}
double
WaveBsmStats::GetBsmPdr (int index)
{
double pdr = 0.0;
if (m_wavePktExpectedReceiveCounts[index - 1] > 0)
{
pdr = (double) m_wavePktInCoverageReceiveCounts[index - 1] / (double) m_wavePktExpectedReceiveCounts[index - 1];
// due to node movement, it is
// possible to receive a packet that is not slightly "within range" that was
// transmitted at the time when the nodes were slightly "out of range"
// thus, prevent overflow of PDR > 100%
if (pdr > 1.0)
{
pdr = 1.0;
}
}
return pdr;
}
double
WaveBsmStats::GetCumulativeBsmPdr (int index)
{
double pdr = 0.0;
if (m_waveTotalPktExpectedReceiveCounts[index - 1] > 0)
{
pdr = (double) m_waveTotalPktInCoverageReceiveCounts[index - 1] / (double) m_waveTotalPktExpectedReceiveCounts[index - 1];
// due to node movement, it is
// possible to receive a packet that is not slightly "within range" that was
// transmitted at the time when the nodes were slightly "out of range"
// thus, prevent overflow of PDR > 100%
if (pdr > 1.0)
{
pdr = 1.0;
}
}
return pdr;
}
void
WaveBsmStats::SetLogging (int log)
{
m_log = log;
}
int
WaveBsmStats::GetLogging ()
{
return m_log;
}
void
WaveBsmStats::SetExpectedRxPktCount (int index, int count)
{
m_wavePktExpectedReceiveCounts[index - 1] = count;
}
void
WaveBsmStats::SetRxPktInRangeCount (int index, int count)
{
m_wavePktInCoverageReceiveCounts[index - 1] = count;
}
void
WaveBsmStats::ResetTotalRxPktCounts (int index)
{
m_waveTotalPktInCoverageReceiveCounts[index - 1] = 0;
m_waveTotalPktExpectedReceiveCounts[index - 1] = 0;
}
} // namespace ns3

View File

@@ -0,0 +1,235 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#ifndef WAVE_BSM_STATS_H
#define WAVE_BSM_STATS_H
#include "ns3/object.h"
#include <vector>
namespace ns3 {
class WaveBsmStats : public Object
/**
* \ingroup wave
* \brief The WaveBsmStats class implements a stats collector for
* IEEE 1609 WAVE (Wireless Access in Vehicular Environments)
* Basic Safety Messages (BSMs). The BSM is a ~200-byte packet that is
* generally broadcast from every vehicle at a nominal rate of 10 Hz.
*/
/*
* Note: This class collects data elements and accessors
* along with methods that calculate metrics from the data
* elements. The data and metrics calculation algorithms
* are collected together here purely to keep them together.
* Future work may need to add additional metric calculations,
* and for now, we are trying to keep all related data and
* algorithms together, although these could easily be
* refactored in the future and moved to separate classes.
* However, it seems that for now, moving the data elements
* or the algorithms separately into different classes could
* lead to confusion over usage.
*/
{
public:
/**
* \brief Constructor
* \return none
*/
WaveBsmStats ();
/**
* \brief Increments the count of transmitted packets
* \return none
*/
void IncTxPktCount ();
/**
* \brief Returns the count of transmitted packets
* \return count of packets transmitted
*/
int GetTxPktCount ();
/*
* Note:
* The WAVE Basic Safety Message (BSM) is broadcast and
* unacknowledged. In order to calculate packet delivery
* ratio (PDR), we must count i) the packets that are
* actually received and ii) the transmitted packets that
* are expected to be received. Both are relative to a
* specified (circular) coverage area.
*
* For example: Say we have three nodes, A, B, and C, each
* separated by 40m, as follows:
*
* A --<40m>-- B --<40m>-- C
*
* Let's assume that the transmission range is 50m, and only
* A is transmitting (i.e. broadcasting). B can receive A's
* broadcasts, while C cannot. Let's assume no dropped packets.
* If we set the coverage area to 100m, then the PDR is 50%,
* because B receives every transmission from A, while C receives
* none of them. However, if we change the effective
* coverage area to 75m then the PDR improves to 100%, because
* B receives 100% of A's transmissions, and C is outside of the
* coverage area, and so does not factor in to the PDR.
*/
/**
* \brief Increments the count of (broadcast) packets expected
* to be received within the coverage area1. Broadcast packets
* (i.e. WAVE Basic Safety Messages) are not ACK'd. For packet
* delivery ratio (PDR), we need to count transmitted packets that
* are expected to be received within the coverage area, even
* though they may not be physically received (due to collisions
* or receiver power thresholds).
* \return none
*/
void IncExpectedRxPktCount (int index);
/**
* \brief Increments the count of actual packets received
* (regardless of coverage area).
* \return none
*/
void IncRxPktCount ();
/**
* \brief Increments the count of actual packets received within
* the coverage area(index). Broadcast packets
* (i.e. WAVE Basic Safety Messages) are not ACK'd. For packet
* delivery ratio (PDR), we need to count only those received packets
* that are actually received within the (circular) coverage area.
* \return none
*/
void IncRxPktInRangeCount (int index);
/**
* \brief Returns the count of packets received
* \return the count of packets received
*/
int GetRxPktCount ();
/**
* \brief Returns the count of expected packets received within range(index)
* \return the count of expected packets received within range(index)
*/
int GetExpectedRxPktCount (int index);
/**
* \brief Increments the count of actual packets recevied within range(index)
* \return the count of actual packets received within range(index)
*/
int GetRxPktInRangeCount (int index);
/**
* \brief Sets the count of packets expected to received
* \param range index
* \param count the count of packets
* \return none
*/
void SetExpectedRxPktCount (int index, int count);
/**
* \brief Sets the count of packets within range that are received
* \param range index
* \param count the count of packets
* \return none
*/
void SetRxPktInRangeCount (int index, int count);
/**
* \brief Resets the count of total packets
* expected and/or within range(index) that are received
* \return none
*/
void ResetTotalRxPktCounts (int index);
/**
* \brief Sets the count of packets transmitted
* \param count the count of packets transmitted
* \return none
*/
void SetTxPktCount (int count);
/**
* \brief Sets the count of packets received
* \param count the count of packets received
* \return none
*/
void SetRxPktCount (int count);
/**
* \brief Increments the count of (application data) bytes transmitted
* not including MAC/PHY overhead
* \param bytes the bytes of application-data transmitted
* \return none
*/
void IncTxByteCount (int bytes);
/**
* \brief Returns the count of (application data) bytes transmitted
* not include MAC/PHY overhead
* \return number of bytes of application-data transmitted
*/
int GetTxByteCount ();
/**
* \brief Returns the BSM Packet Delivery Ratio (PDR)
* which is the percent of expected packets within range(index) that
* are actually received
* \return the packet delivery ratio (PDR) of BSMs.
*/
double GetBsmPdr (int index);
/**
* \brief Returns the cumulative BSM Packet Delivery Ratio (PDR)
* which is the percent of cumulative expected packets within range(index)
* that are actually received
* \return the packet delivery ratio (PDR) of BSMs.
*/
double GetCumulativeBsmPdr (int index);
/**
* \brief Enables/disables logging
* \return none
*/
void SetLogging (int log);
/**
* \brief Gets logging state
* \return logging state
*/
int GetLogging ();
private:
int m_wavePktSendCount;
int m_waveByteSendCount;
int m_wavePktReceiveCount;
std::vector <int> m_wavePktInCoverageReceiveCounts;
std::vector <int> m_wavePktExpectedReceiveCounts;
std::vector <int> m_waveTotalPktInCoverageReceiveCounts;
std::vector <int> m_waveTotalPktExpectedReceiveCounts;
int m_log;
};
} // namespace ns3
#endif /* WAVE_BSM_STATS_H*/

View File

@@ -0,0 +1,413 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#include "ns3/bsm-application.h"
#include "ns3/log.h"
#include "ns3/seq-ts-header.h"
#include "ns3/wave-net-device.h"
#include "ns3/wave-mac-helper.h"
#include "ns3/wave-helper.h"
#include "ns3/mobility-model.h"
#include "ns3/mobility-helper.h"
NS_LOG_COMPONENT_DEFINE ("BsmApplication");
namespace ns3 {
// (Arbitrary) port for establishing socket to transmit WAVE BSMs
int BsmApplication::wavePort = 9080;
NS_OBJECT_ENSURE_REGISTERED (BsmApplication);
TypeId
BsmApplication::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::BsmApplication")
.SetParent<Application> ()
.AddConstructor<BsmApplication> ()
;
return tid;
}
BsmApplication::BsmApplication ()
: m_waveBsmStats (0),
m_txSafetyRangesSq (),
m_TotalSimTime (Seconds (10)),
m_wavePacketSize (200),
m_numWavePackets (1),
m_waveInterval (MilliSeconds (100)),
m_gpsAccuracyNs (10000),
m_adhocTxInterfaces (0),
m_nodesMoving (0),
m_unirv (0),
m_nodeId (0),
m_chAccessMode (0),
m_txMaxDelay (MilliSeconds (10)),
m_prevTxDelay (MilliSeconds (0))
{
NS_LOG_FUNCTION (this);
}
BsmApplication::~BsmApplication ()
{
NS_LOG_FUNCTION (this);
}
void
BsmApplication::DoDispose (void)
{
NS_LOG_FUNCTION (this);
// chain up
Application::DoDispose ();
}
// Application Methods
void BsmApplication::StartApplication () // Called at time specified by Start
{
NS_LOG_FUNCTION (this);
// setup generation of WAVE BSM messages
Time waveInterPacketInterval = m_waveInterval;
// BSMs are not transmitted for the first second
Time startTime = Seconds (1.0);
// total length of time transmitting WAVE packets
Time totalTxTime = m_TotalSimTime - startTime;
// total WAVE packets needing to be sent
m_numWavePackets = (uint32_t) (totalTxTime.GetDouble () / m_waveInterval.GetDouble ());
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
// every node broadcasts WAVE BSM to potentially all other nodes
Ptr<Socket> recvSink = Socket::CreateSocket (GetNode (m_nodeId), tid);
recvSink->SetRecvCallback (MakeCallback (&BsmApplication::ReceiveWavePacket, this));
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), wavePort);
recvSink->Bind (local);
recvSink->BindToNetDevice (GetNetDevice (m_nodeId));
recvSink->SetAllowBroadcast (true);
// dest is broadcast address
InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), wavePort);
recvSink->Connect (remote);
// Transmission start time for each BSM:
// We assume that the start transmission time
// for the first packet will be on a ns-3 time
// "Second" boundary - e.g., 1.0 s.
// However, the actual transmit time must reflect
// additional effects of 1) clock drift and
// 2) transmit delay requirements.
// 1) Clock drift - clocks are not perfectly
// synchronized across all nodes. In a VANET
// we assume all nodes sync to GPS time, which
// itself is assumed accurate to, say, 40-100 ns.
// Thus, the start transmission time must be adjusted
// by some value, t_drift.
// 2) Transmit delay requirements - The US
// minimum performance requirements for V2V
// BSM transmission expect a random delay of
// +/- 5 ms, to avoid simultanous transmissions
// by all vehicles congesting the channel. Thus,
// we need to adjust the start trasmission time by
// some value, t_tx_delay.
// Therefore, the actual transmit time should be:
// t_start = t_time + t_drift + t_tx_delay
// t_drift is always added to t_time.
// t_tx_delay is supposed to be +/- 5ms, but if we
// allow negative numbers the time could drift to a value
// BEFORE the interval start time (i.e., at 100 ms
// boundaries, we do not want to drift into the
// previous interval, such as at 95 ms. Instead,
// we always want to be at the 100 ms interval boundary,
// plus [0..10] ms tx delay.
// Thus, the average t_tx_delay will be
// within the desired range of [0..10] ms of
// (t_time + t_drift)
// WAVE devices sync to GPS time
// and all devices would like to begin broadcasting
// their safety messages immediately at the start of
// the CCH interval. However, if all do so, then
// significant collisions occur. Thus, we assume there
// is some GPS sync accuracy on GPS devices,
// typically 40-100 ns.
// Get a uniformly random number for GPS sync accuracy, in ns.
Time tDrift = NanoSeconds (m_unirv->GetInteger (0, m_gpsAccuracyNs));
// When transmitting at a default rate of 10 Hz,
// the subsystem shall transmit every 100 ms +/-
// a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002]
// Source: CAMP Vehicle Safety Communications 4 Consortium
// On-board Minimum Performance Requirements
// for V2V Safety Systems Version 1.0, December 17, 2014
// max transmit delay (default 10ms)
// get value for transmit delay, as number of ns
uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
// convert random tx delay to ns-3 time
// see note above regarding centering tx delay
// offset by 5ms + a random value.
Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
m_prevTxDelay = txDelay;
Time txTime = startTime + tDrift + txDelay;
// schedule transmission of first packet
Simulator::ScheduleWithContext (recvSink->GetNode ()->GetId (),
txTime, &BsmApplication::GenerateWaveTraffic, this,
recvSink, m_wavePacketSize, m_numWavePackets, waveInterPacketInterval, m_nodeId);
}
void BsmApplication::StopApplication () // Called at time specified by Stop
{
NS_LOG_FUNCTION (this);
}
void
BsmApplication::Setup (Ipv4InterfaceContainer & i,
int nodeId,
Time totalTime,
uint32_t wavePacketSize, // bytes
Time waveInterval,
double gpsAccuracyNs,
std::vector <double> rangesSq, // m ^2
Ptr<WaveBsmStats> waveBsmStats,
std::vector<int> * nodesMoving,
int chAccessMode,
Time txMaxDelay)
{
NS_LOG_FUNCTION (this);
m_unirv = CreateObject<UniformRandomVariable> ();
m_TotalSimTime = totalTime;
m_wavePacketSize = wavePacketSize;
m_waveInterval = waveInterval;
m_gpsAccuracyNs = gpsAccuracyNs;
int size = rangesSq.size ();
m_waveBsmStats = waveBsmStats;
m_nodesMoving = nodesMoving;
m_chAccessMode = chAccessMode;
m_txSafetyRangesSq.clear ();
m_txSafetyRangesSq.resize (size, 0);
for (int index = 0; index < size; index++)
{
// stored as square of value, for optimization
m_txSafetyRangesSq[index] = rangesSq[index];
}
m_adhocTxInterfaces = &i;
m_nodeId = nodeId;
m_txMaxDelay = txMaxDelay;
}
void
BsmApplication::GenerateWaveTraffic (Ptr<Socket> socket, uint32_t pktSize,
uint32_t pktCount, Time pktInterval,
uint32_t sendingNodeId)
{
NS_LOG_FUNCTION (this);
// more packets to send?
if (pktCount > 0)
{
// for now, we cannot tell if each node has
// started mobility. so, as an optimization
// only send if this node is moving
// if not, then skip
int txNodeId = sendingNodeId;
Ptr<Node> txNode = GetNode (txNodeId);
Ptr<MobilityModel> txPosition = txNode->GetObject<MobilityModel> ();
NS_ASSERT (txPosition != 0);
int senderMoving = m_nodesMoving->at (txNodeId);
if (senderMoving != 0)
{
// send it!
socket->Send (Create<Packet> (pktSize));
// count it
m_waveBsmStats->IncTxPktCount ();
m_waveBsmStats->IncTxByteCount (pktSize);
int wavePktsSent = m_waveBsmStats->GetTxPktCount ();
if ((m_waveBsmStats->GetLogging () != 0) && ((wavePktsSent % 1000) == 0))
{
NS_LOG_UNCOND ("Sending WAVE pkt # " << wavePktsSent );
}
// find other nodes within range that would be
// expected to receive this broadbast
int nRxNodes = m_adhocTxInterfaces->GetN ();
for (int i = 0; i < nRxNodes; i++)
{
Ptr<Node> rxNode = GetNode (i);
int rxNodeId = rxNode->GetId ();
if (rxNodeId != txNodeId)
{
Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
NS_ASSERT (rxPosition != 0);
// confirm that the receiving node
// has also started moving in the scenario
// if it has not started moving, then
// it is not a candidate to receive a packet
int receiverMoving = m_nodesMoving->at (rxNodeId);
if (receiverMoving == 1)
{
double distSq = MobilityHelper::GetDistanceSquaredBetween (txNode, rxNode);
if (distSq > 0.0)
{
// dest node within range?
int rangeCount = m_txSafetyRangesSq.size ();
for (int index = 1; index <= rangeCount; index++)
{
if (distSq <= m_txSafetyRangesSq[index - 1])
{
// we should expect dest node to receive broadcast pkt
m_waveBsmStats->IncExpectedRxPktCount (index);
}
}
}
}
}
}
}
// every BSM must be scheduled with a tx time delay
// of +/- (5) ms. See comments in StartApplication().
// we handle this as a tx delay of [0..10] ms
// from the start of the pktInterval boundary
uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
// do not want the tx delay to be cumulative, so
// deduct the previous delay value. thus we adjust
// to schedule the next event at the next pktInterval,
// plus some new [0..10] ms tx delay
Time txTime = pktInterval - m_prevTxDelay + txDelay;
m_prevTxDelay = txDelay;
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (),
txTime, &BsmApplication::GenerateWaveTraffic, this,
socket, pktSize, pktCount - 1, pktInterval, socket->GetNode ()->GetId ());
}
else
{
socket->Close ();
}
}
void BsmApplication::ReceiveWavePacket (Ptr<Socket> socket)
{
NS_LOG_FUNCTION (this);
Ptr<Packet> packet;
while ((packet = socket->Recv ()))
{
Ptr<Node> rxNode = socket->GetNode ();
SocketAddressTag tag;
bool found;
found = packet->PeekPacketTag (tag);
if (found)
{
InetSocketAddress addr = InetSocketAddress::ConvertFrom (tag.GetAddress ());
int nodes = m_adhocTxInterfaces->GetN ();
for (int i = 0; i < nodes; i++)
{
if (addr.GetIpv4 () == m_adhocTxInterfaces->GetAddress (i) )
{
Ptr<Node> txNode = GetNode (i);
HandleReceivedBsmPacket (txNode, rxNode);
}
}
}
}
}
void BsmApplication::HandleReceivedBsmPacket (Ptr<Node> txNode,
Ptr<Node> rxNode)
{
NS_LOG_FUNCTION (this);
m_waveBsmStats->IncRxPktCount ();
Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
NS_ASSERT (rxPosition != 0);
// confirm that the receiving node
// has also started moving in the scenario
// if it has not started moving, then
// it is not a candidate to receive a packet
int rxNodeId = rxNode->GetId ();
int receiverMoving = m_nodesMoving->at (rxNodeId);
if (receiverMoving == 1)
{
double rxDistSq = MobilityHelper::GetDistanceSquaredBetween (rxNode, txNode);
if (rxDistSq > 0.0)
{
int rangeCount = m_txSafetyRangesSq.size ();
for (int index = 1; index <= rangeCount; index++)
{
if (rxDistSq <= m_txSafetyRangesSq[index - 1])
{
m_waveBsmStats->IncRxPktInRangeCount (index);
}
}
}
}
}
int64_t
BsmApplication::AssignStreams (int64_t streamIndex)
{
NS_LOG_FUNCTION (this);
NS_ASSERT (m_unirv); // should be set by Setup() prevoiusly
m_unirv->SetStream (streamIndex);
return 1;
}
Ptr<Node>
BsmApplication::GetNode (int id)
{
NS_LOG_FUNCTION (this);
std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
Ptr<Ipv4> pp = interface.first;
Ptr<Node> node = pp->GetObject<Node> ();
return node;
}
Ptr<NetDevice>
BsmApplication::GetNetDevice (int id)
{
NS_LOG_FUNCTION (this);
std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
Ptr<Ipv4> pp = interface.first;
Ptr<NetDevice> device = pp->GetObject<NetDevice> ();
return device;
}
} // namespace ns3

View File

@@ -0,0 +1,175 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2014 North Carolina State University
*
* 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: Scott E. Carpenter <scarpen@ncsu.edu>
*
*/
#ifndef BSM_APPLICATION_H
#define BSM_APPLICATION_H
#include "ns3/application.h"
#include "ns3/wave-bsm-stats.h"
#include "ns3/random-variable-stream.h"
#include "ns3/internet-stack-helper.h"
namespace ns3 {
/**
* \ingroup wave
* \brief The BsmApplication class sends and receives the
* IEEE 1609 WAVE (Wireless Access in Vehicular Environments)
* Basic Safety Messages (BSMs) and uses the WaveBsmStats class
* to manage statistics about BSMs transmitted and received
* The BSM is a ~200-byte packet that is
* generally broadcast from every vehicle at a nominal rate of 10 Hz.
*/
class BsmApplication : public Application
{
public:
static TypeId GetTypeId (void);
/**
* \brief Constructor
* \return none
*/
BsmApplication ();
virtual ~BsmApplication ();
/**
* \brief Setup BSM generation parameters for a node
* \param i IPv4 interface container
* \param nodeId identifier of the node (index into container)
* \param totalTime total amount of time that BSM packets should be transmitted
* \param wavePacketSize the size, in bytes, of a WAVE BSM
* \param waveInterval the time, in seconds, between each WAVE BSM transmission,
* typically 10 Hz (0.1 second)
* \param gpsAccuracy the timing synchronization accuracy of GPS time, in seconds.
* GPS time-sync is ~40-100 ns. Universally synchronized time among all vehicles
* will result in all vehicles transmitting safety messages simultaneously, leading
* to excessive wireless collisions.
* \param range the expected transmission range, in m ^ 2.
* \param collection class for WAVE BSM statistics
* \param indicators of whether or not node(s) are moving
* \return none
*/
void Setup (Ipv4InterfaceContainer & i,
int nodeId,
Time totalTime,
uint32_t wavePacketSize, // bytes
Time waveInterval,
double gpsAccuracyNs,
std::vector <double> rangesSq, // m ^ 2
Ptr<WaveBsmStats> waveBsmStats,
std::vector<int> * nodesMoving,
int mode,
Time txDelay);
/**
* Assign a fixed random variable stream number to the random variables
* used by this model. Return the number of streams (possibly zero) that
* have been assigned. The Install() method should have previously been
* called by the user.
*
* \param stream first stream index to use
* \return the number of stream indices assigned by this helper
*/
int64_t AssignStreams (int64_t streamIndex);
/**
* (Arbitrary) port number that is used to create a socket for transmitting WAVE BSMs.
*/
static int wavePort;
protected:
virtual void DoDispose (void);
private:
// inherited from Application base class.
virtual void StartApplication (void); // Called at time specified by Start
virtual void StopApplication (void); // Called at time specified by Stop
/**
* \brief Creates and transmits a WAVE BSM packet
* \param socket socket to use for transmission
* \param pktSize the size, in bytes, of the WAVE BSM packet
* \param pktCount the number of remaining WAVE BSM packets to be transmitted
* \param pktInterval the interval, in seconds, until the next packet
* should be transmitted
* \return none
*/
void GenerateWaveTraffic (Ptr<Socket> socket, uint32_t pktSize,
uint32_t pktCount, Time pktInterval,
uint32_t sendingNodeId);
/**
* \brief Receive a WAVE BSM packet
* \param socket the receiving socket
* \return none
*/
void ReceiveWavePacket (Ptr<Socket> socket);
/**
* \brief Handle the receipt of a WAVE BSM packet from sender to receiver
* \param txNode the sending node
* \param rxNode the receiving node
* \return none
*/
void HandleReceivedBsmPacket (Ptr<Node> txNode,
Ptr<Node> rxNode);
/**
* \brief Get the node for the desired id
* \param id the id of the desired node
* \return ptr to the desired node
*/
Ptr<Node> GetNode (int id);
/**
* \brief Get the net device for the desired id
* \param id the id of the desired net device
* \return ptr to the desired net device
*/
Ptr<NetDevice> GetNetDevice (int id);
Ptr<WaveBsmStats> m_waveBsmStats;
// tx safety range squared, for optimization
std::vector <double> m_txSafetyRangesSq;
Time m_TotalSimTime;
uint32_t m_wavePacketSize; // bytes
uint32_t m_numWavePackets;
Time m_waveInterval;
double m_gpsAccuracyNs;
Ipv4InterfaceContainer * m_adhocTxInterfaces;
std::vector<int> * m_nodesMoving;
Ptr<UniformRandomVariable> m_unirv;
int m_nodeId;
// WAVE channel access mode. 0=continuous PHY; 1=channel-switching
int m_chAccessMode;
// When transmitting at a default rate of 10 Hz,
// the subsystem shall transmit every 100 ms +/-
// a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002]
// Source: CAMP Vehicle Safety Communications 4 Consortium
// On-board Minimum Performance Requirements
// for V2V Safety Systems Version 1.0, December 17, 2014
// max transmit delay (default 10ms)
Time m_txMaxDelay;
Time m_prevTxDelay;
};
} // namespace ns3
#endif /* BSM_APPLICATION_H*/