RV battery model and WiFi energy example
This commit is contained in:
1 parent
262886360f
commit
db55c0c2a8
23 files changed
+2336
-288
No files matched your search
@@ -94,6 +94,10 @@ This application only works with NS3_SOCK_STREAM and NS3_SOCK_SEQPACKET sockets,
|
||||
for example TCP sockets and not UDP sockets. A helper class exists to
|
||||
facilitate creating BulkSendApplications. The API for the helper class
|
||||
is similar to existing application helper classes, for example, OnOff.
|
||||
</p></li>
|
||||
|
||||
<li><b>Rakhmatov Vrudhula non-linear battery model</b>
|
||||
<p>New class and helper for this battery model. </p></li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -71,6 +71,12 @@ New user-visible features
|
||||
application only works with SOCK_STREAM and SOCK_SEQPACKET
|
||||
sockets, for example TCP sockets and not UDP sockets.
|
||||
|
||||
- Extensions to the energy models: 1) a new Rakhmatov Vrudhula
|
||||
non-linear battery model, 2) additional support for modeling
|
||||
energy consumption in WiFi devices, 3) an example for how to add
|
||||
energy models to a WiFi-based simulation (in examples/energy/
|
||||
directory).
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
The following lists many of the bugs fixed or small feature additions
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/common-module.h"
|
||||
#include "ns3/node-module.h"
|
||||
#include "ns3/helper-module.h"
|
||||
#include "ns3/mobility-module.h"
|
||||
#include "ns3/contrib-module.h"
|
||||
#include "ns3/wifi-module.h"
|
||||
#include "ns3/energy-module.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("EnergyExample");
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
/**
|
||||
* \param socket Pointer to socket.
|
||||
*
|
||||
* Packet receiving sink.
|
||||
*/
|
||||
void
|
||||
ReceivePacket (Ptr<Socket> socket)
|
||||
{
|
||||
Ptr<Packet> packet;
|
||||
Address from;
|
||||
while (packet = socket->RecvFrom (from))
|
||||
{
|
||||
if (packet->GetSize () > 0)
|
||||
{
|
||||
InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (from);
|
||||
NS_LOG_UNCOND ("--\nReceived one packet! Socket: "<< iaddr.GetIpv4 ()
|
||||
<< " port: " << iaddr.GetPort () << " at time = " <<
|
||||
Simulator::Now ().GetSeconds () << "\n--");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \param socket Pointer to socket.
|
||||
* \param pktSize Packet size.
|
||||
* \param n Pointer to node.
|
||||
* \param pktCount Number of packets to generate.
|
||||
* \param pktInterval Packet sending interval.
|
||||
*
|
||||
* Traffic generator.
|
||||
*/
|
||||
static void
|
||||
GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, Ptr<Node> n,
|
||||
uint32_t pktCount, Time pktInterval)
|
||||
{
|
||||
if (pktCount > 0)
|
||||
{
|
||||
socket->Send (Create<Packet> (pktSize));
|
||||
Simulator::Schedule (pktInterval, &GenerateTraffic, socket, pktSize, n,
|
||||
pktCount - 1, pktInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
socket->Close ();
|
||||
}
|
||||
}
|
||||
|
||||
/// Trace function for remaining energy at node.
|
||||
void
|
||||
RemainingEnergy (double oldValue, double remainingEnergy)
|
||||
{
|
||||
NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
|
||||
<< "s Current remaining energy = " << remainingEnergy << "J");
|
||||
}
|
||||
|
||||
/// Trace function for total energy consumption at node.
|
||||
void
|
||||
TotalEnergy (double oldValue, double totalEnergy)
|
||||
{
|
||||
NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
|
||||
<< "s Total energy consumed by radio = " << totalEnergy << "J");
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
/*
|
||||
LogComponentEnable ("EnergySource", LOG_LEVEL_DEBUG);
|
||||
LogComponentEnable ("BasicEnergySource", LOG_LEVEL_DEBUG);
|
||||
LogComponentEnable ("DeviceEnergyModel", LOG_LEVEL_DEBUG);
|
||||
LogComponentEnable ("WifiRadioEnergyModel", LOG_LEVEL_DEBUG);
|
||||
*/
|
||||
|
||||
std::string phyMode ("DsssRate1Mbps");
|
||||
double Prss = -80; // dBm
|
||||
uint32_t PpacketSize = 200; // bytes
|
||||
bool verbose = false;
|
||||
|
||||
// simulation parameters
|
||||
uint32_t numPackets = 10000; // number of packets to send
|
||||
double interval = 1; // seconds
|
||||
double startTime = 0.0; // seconds
|
||||
double distanceToRx = 100.0; // meters
|
||||
/*
|
||||
* This is a magic number used to set the transmit power, based on other
|
||||
* configuration.
|
||||
*/
|
||||
double offset = 81;
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("phyMode", "Wifi Phy mode", phyMode);
|
||||
cmd.AddValue ("Prss", "Intended primary RSS (dBm)", Prss);
|
||||
cmd.AddValue ("PpacketSize", "size of application packet sent", PpacketSize);
|
||||
cmd.AddValue ("numPackets", "Total number of packets to send", numPackets);
|
||||
cmd.AddValue ("startTime", "Simulation start time", startTime);
|
||||
cmd.AddValue ("distanceToRx", "X-Axis distance between nodes", distanceToRx);
|
||||
cmd.AddValue ("verbose", "Turn on all device log components", verbose);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
// Convert to time object
|
||||
Time interPacketInterval = Seconds (interval);
|
||||
|
||||
// disable fragmentation for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
|
||||
StringValue ("2200"));
|
||||
// turn off RTS/CTS for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
|
||||
StringValue ("2200"));
|
||||
// Fix non-unicast data rate to be the same as that of unicast
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
|
||||
StringValue (phyMode));
|
||||
|
||||
NodeContainer c;
|
||||
c.Create (2); // create 2 nodes
|
||||
NodeContainer networkNodes;
|
||||
networkNodes.Add (c.Get (0));
|
||||
networkNodes.Add (c.Get (1));
|
||||
|
||||
// The below set of helpers will help us to put together the wifi NICs we want
|
||||
WifiHelper wifi;
|
||||
if (verbose)
|
||||
{
|
||||
wifi.EnableLogComponents ();
|
||||
}
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
|
||||
|
||||
/** Wifi PHY **/
|
||||
/***************************************************************************/
|
||||
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
|
||||
wifiPhy.Set ("RxGain", DoubleValue (-10));
|
||||
wifiPhy.Set ("TxGain", DoubleValue (offset + Prss));
|
||||
wifiPhy.Set ("CcaMode1Threshold", DoubleValue (0.0));
|
||||
/***************************************************************************/
|
||||
|
||||
/** wifi channel **/
|
||||
YansWifiChannelHelper wifiChannel;
|
||||
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
|
||||
// create wifi channel
|
||||
Ptr<YansWifiChannel> wifiChannelPtr = wifiChannel.Create ();
|
||||
wifiPhy.SetChannel (wifiChannelPtr);
|
||||
|
||||
/** MAC layer **/
|
||||
// Add a non-QoS upper MAC, and disable rate control
|
||||
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode",
|
||||
StringValue (phyMode), "ControlMode",
|
||||
StringValue (phyMode));
|
||||
// Set it to ad-hoc mode
|
||||
wifiMac.SetType ("ns3::AdhocWifiMac");
|
||||
|
||||
/** install PHY + MAC **/
|
||||
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, networkNodes);
|
||||
|
||||
/** mobility **/
|
||||
MobilityHelper mobility;
|
||||
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
|
||||
positionAlloc->Add (Vector (0.0, 0.0, 0.0));
|
||||
positionAlloc->Add (Vector (2 * distanceToRx, 0.0, 0.0));
|
||||
mobility.SetPositionAllocator (positionAlloc);
|
||||
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
||||
mobility.Install (c);
|
||||
|
||||
/** Energy Model **/
|
||||
/***************************************************************************/
|
||||
/* energy source */
|
||||
BasicEnergySourceHelper basicSourceHelper;
|
||||
// configure energy source
|
||||
basicSourceHelper.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (0.1));
|
||||
// install source
|
||||
EnergySourceContainer sources = basicSourceHelper.Install (c);
|
||||
/* device energy model */
|
||||
WifiRadioEnergyModelHelper radioEnergyHelper;
|
||||
// configure radio energy model
|
||||
radioEnergyHelper.Set ("TxCurrentA", DoubleValue (0.0174));
|
||||
// install device model
|
||||
DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
|
||||
/***************************************************************************/
|
||||
|
||||
/** Internet stack **/
|
||||
InternetStackHelper internet;
|
||||
internet.Install (networkNodes);
|
||||
|
||||
Ipv4AddressHelper ipv4;
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
ipv4.SetBase ("10.1.1.0", "255.255.255.0");
|
||||
Ipv4InterfaceContainer i = ipv4.Assign (devices);
|
||||
|
||||
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
|
||||
Ptr<Socket> recvSink = Socket::CreateSocket (networkNodes.Get (1), tid); // node 1, receiver
|
||||
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
|
||||
recvSink->Bind (local);
|
||||
recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));
|
||||
|
||||
Ptr<Socket> source = Socket::CreateSocket (networkNodes.Get (0), tid); // node 0, sender
|
||||
InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetBroadcast (), 80);
|
||||
source->SetAllowBroadcast (true);
|
||||
source->Connect (remote);
|
||||
|
||||
/** connect trace sources **/
|
||||
/***************************************************************************/
|
||||
// all sources are connected to node 1
|
||||
// energy source
|
||||
Ptr<BasicEnergySource> basicSourcePtr = DynamicCast<BasicEnergySource> (sources.Get (1));
|
||||
basicSourcePtr->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback (&RemainingEnergy));
|
||||
// device energy model
|
||||
Ptr<DeviceEnergyModel> basicRadioModelPtr =
|
||||
basicSourcePtr->FindDeviceEnergyModels ("ns3::WifiRadioEnergyModel").Get (0);
|
||||
NS_ASSERT (basicRadioModelPtr != NULL);
|
||||
basicRadioModelPtr->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&TotalEnergy));
|
||||
/***************************************************************************/
|
||||
|
||||
|
||||
/** simulation setup **/
|
||||
// start traffic
|
||||
Simulator::Schedule (Seconds (startTime), &GenerateTraffic, source, PpacketSize,
|
||||
networkNodes.Get (0), numPackets, interPacketInterval);
|
||||
|
||||
Simulator::Stop (Seconds (10.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../../waf "$@"
|
||||
@@ -0,0 +1,5 @@
|
||||
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
|
||||
|
||||
def build(bld):
|
||||
obj = bld.create_ns3_program('energy-model-example', ['core', 'simulator', 'mobility', 'wifi', 'energy', 'internet-stack'])
|
||||
obj.source = 'energy-model-example.cc'
|
||||
@@ -93,6 +93,7 @@ DeviceEnergyModelHelper::Install (Ptr<NetDevice> device,
|
||||
{
|
||||
NS_ASSERT (device != NULL);
|
||||
NS_ASSERT (source != NULL);
|
||||
// check to make sure source and net device are on the same node
|
||||
NS_ASSERT (device->GetNode () == source->GetNode ());
|
||||
DeviceEnergyModelContainer container (DoInstall (device, source));
|
||||
return container;
|
||||
@@ -108,6 +109,7 @@ DeviceEnergyModelHelper::Install (NetDeviceContainer deviceContainer,
|
||||
EnergySourceContainer::Iterator src = sourceContainer.Begin ();
|
||||
while (dev != deviceContainer.End ())
|
||||
{
|
||||
// check to make sure source and net device are on the same node
|
||||
NS_ASSERT ((*dev)->GetNode () == (*src)->GetNode ());
|
||||
Ptr<DeviceEnergyModel> model = DoInstall (*dev, *src);
|
||||
container.Add (model);
|
||||
|
||||
@@ -118,6 +118,13 @@ EnergySourceContainer::Add (std::string sourceName)
|
||||
void
|
||||
EnergySourceContainer::DoDispose (void)
|
||||
{
|
||||
// call Object::Dispose for all EnergySource objects
|
||||
for (std::vector< Ptr<EnergySource> >::iterator i = m_sources.begin ();
|
||||
i != m_sources.end (); i++)
|
||||
{
|
||||
(*i)->DisposeDeviceModels ();
|
||||
(*i)->Dispose ();
|
||||
}
|
||||
m_sources.clear ();
|
||||
}
|
||||
|
||||
@@ -126,9 +133,10 @@ EnergySourceContainer::DoStart (void)
|
||||
{
|
||||
// call Object::Start for all EnergySource objects
|
||||
for (std::vector< Ptr<EnergySource> >::iterator i = m_sources.begin ();
|
||||
i != m_sources.end (); i++)
|
||||
i != m_sources.end (); i++)
|
||||
{
|
||||
(*i)->Start ();
|
||||
(*i)->StartDeviceModels ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#include "rv-battery-model-helper.h"
|
||||
#include "ns3/energy-source.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
RvBatteryModelHelper::RvBatteryModelHelper ()
|
||||
{
|
||||
m_rvBatteryModel.SetTypeId ("ns3::RvBatteryModel");
|
||||
}
|
||||
|
||||
RvBatteryModelHelper::~RvBatteryModelHelper ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModelHelper::Set (std::string name, const AttributeValue &v)
|
||||
{
|
||||
m_rvBatteryModel.Set (name, v);
|
||||
}
|
||||
|
||||
Ptr<EnergySource>
|
||||
RvBatteryModelHelper::DoInstall (Ptr<Node> node) const
|
||||
{
|
||||
NS_ASSERT (node != NULL);
|
||||
// check if energy source already exists
|
||||
Ptr<EnergySource> source = node->GetObject<EnergySource> ();
|
||||
if (source != NULL)
|
||||
{
|
||||
NS_FATAL_ERROR ("Energy source already installed!");
|
||||
}
|
||||
source = m_rvBatteryModel.Create<EnergySource> ();
|
||||
NS_ASSERT (source != NULL);
|
||||
source->SetNode (node);
|
||||
return source;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -0,0 +1,50 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#ifndef RV_BATTERY_MODEL_HELPER_H
|
||||
#define RV_BATTERY_MODEL_HELPER_H
|
||||
|
||||
#include "energy-model-helper.h"
|
||||
#include "ns3/node.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Creates a RvBatteryModel object.
|
||||
*/
|
||||
class RvBatteryModelHelper : public EnergySourceHelper
|
||||
{
|
||||
public:
|
||||
RvBatteryModelHelper ();
|
||||
~RvBatteryModelHelper ();
|
||||
|
||||
void Set (std::string name, const AttributeValue &v);
|
||||
|
||||
private:
|
||||
virtual Ptr<EnergySource> DoInstall (Ptr<Node> node) const;
|
||||
|
||||
private:
|
||||
ObjectFactory m_rvBatteryModel;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* RV_BATTERY_MODEL_HELPER_H */
|
||||
@@ -67,23 +67,18 @@ WifiRadioEnergyModelHelper::DoInstall (Ptr<NetDevice> device,
|
||||
NS_FATAL_ERROR ("NetDevice type is not WifiNetDevice!");
|
||||
}
|
||||
Ptr<Node> node = device->GetNode ();
|
||||
Ptr<WifiRadioEnergyModel> model = m_radioEnergy.Create ()->
|
||||
GetObject<WifiRadioEnergyModel> ();
|
||||
Ptr<WifiRadioEnergyModel> model = m_radioEnergy.Create ()->GetObject<WifiRadioEnergyModel> ();
|
||||
NS_ASSERT (model != NULL);
|
||||
// set node pointer
|
||||
model->SetNode (node);
|
||||
// set energy source pointer
|
||||
model->SetEnergySource (source);
|
||||
// set energy depletion callback
|
||||
model->SetEnergyDepletionCallback (m_depletionCallback);
|
||||
// add model to device model list in energy source
|
||||
source->AppendDeviceEnergyModel (model);
|
||||
// create and install energy model callback
|
||||
// create and register energy model phy listener
|
||||
Ptr<WifiNetDevice> wifiDevice = DynamicCast<WifiNetDevice> (device);
|
||||
Ptr<WifiPhy> wifiPhy = wifiDevice->GetPhy ();
|
||||
DeviceEnergyModel::ChangeStateCallback callback;
|
||||
callback = MakeCallback (&DeviceEnergyModel::ChangeState, model);
|
||||
//wifiPhy->SetEnergyModelCallback (callback);
|
||||
wifiPhy->RegisterListener (model->GetPhyListener ());
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,28 +90,25 @@ BasicEnergySource::SetSupplyVoltage (double supplyVoltageV)
|
||||
void
|
||||
BasicEnergySource::SetEnergyUpdateInterval (Time interval)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_FUNCTION (this << interval);
|
||||
m_energyUpdateInterval = interval;
|
||||
}
|
||||
|
||||
Time
|
||||
BasicEnergySource::GetEnergyUpdateInterval (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_energyUpdateInterval;
|
||||
}
|
||||
|
||||
double
|
||||
BasicEnergySource::GetSupplyVoltage (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_supplyVoltageV;
|
||||
}
|
||||
|
||||
double
|
||||
BasicEnergySource::GetInitialEnergy (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_initialEnergyJ;
|
||||
}
|
||||
|
||||
@@ -133,33 +130,11 @@ BasicEnergySource::GetEnergyFraction (void)
|
||||
return m_remainingEnergyJ / m_initialEnergyJ;
|
||||
}
|
||||
|
||||
void
|
||||
BasicEnergySource::DecreaseRemainingEnergy (double energyJ)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << energyJ);
|
||||
NS_ASSERT (energyJ >= 0);
|
||||
m_remainingEnergyJ -= energyJ;
|
||||
// check if remaining energy is 0
|
||||
if (m_remainingEnergyJ <= 0)
|
||||
{
|
||||
HandleEnergyDrainedEvent ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BasicEnergySource::IncreaseRemainingEnergy (double energyJ)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << energyJ);
|
||||
NS_ASSERT (energyJ >= 0);
|
||||
m_remainingEnergyJ += energyJ;
|
||||
}
|
||||
|
||||
void
|
||||
BasicEnergySource::UpdateEnergySource (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_DEBUG ("BasicEnergySource:Updating remaining energy at node #" <<
|
||||
GetNode ()->GetId ());
|
||||
NS_LOG_DEBUG ("BasicEnergySource:Updating remaining energy.");
|
||||
|
||||
// do not update if simulation has finished
|
||||
if (Simulator::IsFinished ())
|
||||
@@ -208,8 +183,7 @@ void
|
||||
BasicEnergySource::HandleEnergyDrainedEvent (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_DEBUG ("BasicEnergySource:Energy depleted at node #" <<
|
||||
GetNode ()->GetId ());
|
||||
NS_LOG_DEBUG ("BasicEnergySource:Energy depleted!");
|
||||
NotifyEnergyDrained (); // notify DeviceEnergyModel objects
|
||||
m_remainingEnergyJ = 0; // energy never goes below 0
|
||||
}
|
||||
|
||||
@@ -67,20 +67,6 @@ public:
|
||||
*/
|
||||
virtual double GetEnergyFraction (void);
|
||||
|
||||
/**
|
||||
* \param energyJ Amount of energy (in Joules) to decrease from energy source.
|
||||
*
|
||||
* Implements DecreaseRemainingEnergy.
|
||||
*/
|
||||
virtual void DecreaseRemainingEnergy (double energyJ);
|
||||
|
||||
/**
|
||||
* \param energyJ Amount of energy (in Joules) to increase from energy source.
|
||||
*
|
||||
* Implements IncreaseRemainingEnergy.
|
||||
*/
|
||||
virtual void IncreaseRemainingEnergy (double energyJ);
|
||||
|
||||
/**
|
||||
* Implements UpdateEnergySource.
|
||||
*/
|
||||
@@ -116,7 +102,10 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
/// Defined in ns3::Object
|
||||
void DoStart (void);
|
||||
|
||||
/// Defined in ns3::Object
|
||||
void DoDispose (void);
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,20 +52,6 @@ public:
|
||||
DeviceEnergyModel ();
|
||||
virtual ~DeviceEnergyModel ();
|
||||
|
||||
/**
|
||||
* \brief Sets pointer to node containing this EnergySource.
|
||||
*
|
||||
* \param node Pointer to node containing this EnergySource.
|
||||
*/
|
||||
virtual void SetNode (Ptr<Node> node) = 0;
|
||||
|
||||
/**
|
||||
* \brief Gets pointer to node containing this EnergySource.
|
||||
*
|
||||
* \returns Pointer to node containing this EnergySource.
|
||||
*/
|
||||
virtual Ptr<Node> GetNode (void) const = 0;
|
||||
|
||||
/**
|
||||
* \param source Pointer to energy source installed on node.
|
||||
*
|
||||
|
||||
@@ -47,7 +47,6 @@ EnergySource::~EnergySource ()
|
||||
void
|
||||
EnergySource::SetNode (Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << node);
|
||||
NS_ASSERT (node != NULL);
|
||||
m_node = node;
|
||||
}
|
||||
@@ -55,7 +54,6 @@ EnergySource::SetNode (Ptr<Node> node)
|
||||
Ptr<Node>
|
||||
EnergySource::GetNode (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_node;
|
||||
}
|
||||
|
||||
@@ -99,6 +97,34 @@ EnergySource::FindDeviceEnergyModels (std::string name)
|
||||
return container;
|
||||
}
|
||||
|
||||
void
|
||||
EnergySource::StartDeviceModels (void)
|
||||
{
|
||||
/*
|
||||
* Device models are not aggregated to the node, hence we have to manually
|
||||
* call dispose method here.
|
||||
*/
|
||||
DeviceEnergyModelContainer::Iterator i;
|
||||
for (i = m_models.Begin (); i != m_models.End (); i++)
|
||||
{
|
||||
(*i)->Start ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EnergySource::DisposeDeviceModels (void)
|
||||
{
|
||||
/*
|
||||
* Device models are not aggregated to the node, hence we have to manually
|
||||
* call dispose method here.
|
||||
*/
|
||||
DeviceEnergyModelContainer::Iterator i;
|
||||
for (i = m_models.Begin (); i != m_models.End (); i++)
|
||||
{
|
||||
(*i)->Dispose ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Private function starts here.
|
||||
*/
|
||||
@@ -107,7 +133,7 @@ void
|
||||
EnergySource::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_models.Clear ();
|
||||
BreakDeviceEnergyModelRefCycle ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -96,22 +96,6 @@ public:
|
||||
*/
|
||||
virtual double GetEnergyFraction (void) = 0;
|
||||
|
||||
/**
|
||||
* \param energyJ Amount of energy to decrease (in Joules)
|
||||
*
|
||||
* This function decreases the remaining energy in the energy source by the
|
||||
* specified amount. Provides linear interface for direct energy deduction.
|
||||
*/
|
||||
virtual void DecreaseRemainingEnergy (double energyJ) = 0;
|
||||
|
||||
/**
|
||||
* \param energyJ Amount of energy to increase (in Joules)
|
||||
*
|
||||
* This function increases the remaining energy in the energy source by the
|
||||
* specified amount. Provides linear interface for direct energy increase.
|
||||
*/
|
||||
virtual void IncreaseRemainingEnergy (double energyJ) = 0;
|
||||
|
||||
/**
|
||||
* This function goes through the list of DeviceEnergyModels to obtain total
|
||||
* current draw at the energy source and updates remaining energy. Called by
|
||||
@@ -154,11 +138,27 @@ public:
|
||||
*/
|
||||
DeviceEnergyModelContainer FindDeviceEnergyModels (std::string name);
|
||||
|
||||
/**
|
||||
* Calls Start () method of the device energy models. Device energy models are
|
||||
* not aggregated to the node, therefore we need to manually start them here.
|
||||
* Called by EnergySourceContainer, which is aggregated to the node.
|
||||
*/
|
||||
void StartDeviceModels (void);
|
||||
|
||||
/**
|
||||
* Calls Dispose () method of the device energy models. Device energy models
|
||||
* are not aggregated to the node, therefore we need to manually start them
|
||||
* here. Called by EnergySourceContainer, which is aggregated to the node.
|
||||
*/
|
||||
void DisposeDeviceModels (void);
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* All child's implementation must call BreakDeviceEnergyModelRefCycle to
|
||||
* ensure reference cycles to DeviceEnergyModel objects are broken.
|
||||
*
|
||||
* Defined in ns3::Object
|
||||
*/
|
||||
virtual void DoDispose (void);
|
||||
|
||||
@@ -169,7 +169,8 @@ private:
|
||||
DeviceEnergyModelContainer m_models;
|
||||
|
||||
/**
|
||||
* Pointer to node containing this EnergySource.
|
||||
* Pointer to node containing this EnergySource. Used by helper class to make
|
||||
* sure device models are installed onto the corresponding node.
|
||||
*/
|
||||
Ptr<Node> m_node;
|
||||
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#include "rv-battery-model.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include <math.h>
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("RvBatteryModel");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (RvBatteryModel);
|
||||
|
||||
TypeId
|
||||
RvBatteryModel::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::RvBatteryModel")
|
||||
.SetParent<EnergySource> ()
|
||||
.AddConstructor<RvBatteryModel> ()
|
||||
.AddAttribute ("RvBatteryModelPeriodicEnergyUpdateInterval",
|
||||
"RV battery model sampling interval.",
|
||||
TimeValue (Seconds (1.0)),
|
||||
MakeTimeAccessor (&RvBatteryModel::SetSamplingInterval,
|
||||
&RvBatteryModel::GetSamplingInterval),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("RvBatteryModelOpenCircuitVoltage",
|
||||
"RV battery model open circuit voltage.",
|
||||
DoubleValue (4.1),
|
||||
MakeDoubleAccessor (&RvBatteryModel::SetOpenCircuitVoltage,
|
||||
&RvBatteryModel::GetOpenCircuitVoltage),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("RvBatteryModelCutoffVoltage",
|
||||
"RV battery model cutoff voltage.",
|
||||
DoubleValue (3.0),
|
||||
MakeDoubleAccessor (&RvBatteryModel::SetCutoffVoltage,
|
||||
&RvBatteryModel::GetCutoffVoltage),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("RvBatteryModelAlphaValue",
|
||||
"RV battery model alpha value.",
|
||||
DoubleValue (35220.0),
|
||||
MakeDoubleAccessor (&RvBatteryModel::SetAlpha,
|
||||
&RvBatteryModel::GetAlpha),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("RvBatteryModelBetaValue",
|
||||
"RV battery model beta value.",
|
||||
DoubleValue (0.637),
|
||||
MakeDoubleAccessor (&RvBatteryModel::SetBeta,
|
||||
&RvBatteryModel::GetBeta),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("RvBatteryModelNumOfTerms",
|
||||
"The number of terms of the infinite sum for estimating battery level.",
|
||||
IntegerValue (10), // value used in paper
|
||||
MakeIntegerAccessor (&RvBatteryModel::SetNumOfTerms,
|
||||
&RvBatteryModel::GetNumOfTerms),
|
||||
MakeIntegerChecker<int> ())
|
||||
.AddTraceSource ("RvBatteryModelBatteryLevel",
|
||||
"RV battery model battery level.",
|
||||
MakeTraceSourceAccessor (&RvBatteryModel::m_batteryLevel))
|
||||
.AddTraceSource ("RvBatteryModelBatteryLifetime",
|
||||
"RV battery model battery lifetime.",
|
||||
MakeTraceSourceAccessor (&RvBatteryModel::m_lifetime))
|
||||
;
|
||||
return tid;
|
||||
}
|
||||
|
||||
RvBatteryModel::RvBatteryModel ()
|
||||
{
|
||||
m_lastSampleTime = Seconds (0.0);
|
||||
m_previousLoad = 0.0;
|
||||
m_batteryLevel = 1; // fully charged
|
||||
m_lifetime = Seconds (0.0);
|
||||
}
|
||||
|
||||
RvBatteryModel::~RvBatteryModel ()
|
||||
{
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetInitialEnergy (void) const
|
||||
{
|
||||
return m_alpha * GetSupplyVoltage ();
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetSupplyVoltage (void) const
|
||||
{
|
||||
// average of Voc and Vcutoff
|
||||
return (m_openCircuitVoltage - m_cutoffVoltage) / 2 + m_cutoffVoltage;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetRemainingEnergy (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
UpdateEnergySource ();
|
||||
return m_alpha * GetSupplyVoltage () * m_batteryLevel;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetEnergyFraction (void)
|
||||
{
|
||||
return GetBatteryLevel ();
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::UpdateEnergySource (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
|
||||
// do not update if battery is already dead
|
||||
if (m_batteryLevel <= 0)
|
||||
{
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Battery is dead!");
|
||||
return;
|
||||
}
|
||||
|
||||
// do not update if simulation has finished
|
||||
if (Simulator::IsFinished ())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Updating remaining energy!");
|
||||
|
||||
m_currentSampleEvent.Cancel ();
|
||||
|
||||
double currentLoad = CalculateTotalCurrent () * 1000; // must be in mA
|
||||
double calculatedAlpha = Discharge (currentLoad, Simulator::Now ());
|
||||
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Calculated alpha = " << calculatedAlpha <<
|
||||
" time = " << Simulator::Now ().GetSeconds ());
|
||||
|
||||
// calculate battery level
|
||||
m_batteryLevel = 1 - (calculatedAlpha / m_alpha);
|
||||
if (m_batteryLevel < 0)
|
||||
{
|
||||
m_batteryLevel = 0;
|
||||
}
|
||||
|
||||
// check if battery is dead.
|
||||
if (calculatedAlpha >= m_alpha)
|
||||
{
|
||||
m_lifetime = Simulator::Now ();
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Battery is dead!");
|
||||
HandleEnergyDrainedEvent ();
|
||||
return; // stop periodic sampling
|
||||
}
|
||||
|
||||
m_previousLoad = currentLoad;
|
||||
m_lastSampleTime = Simulator::Now ();
|
||||
m_currentSampleEvent = Simulator::Schedule (m_samplingInterval,
|
||||
&RvBatteryModel::UpdateEnergySource,
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetSamplingInterval (Time interval)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << interval);
|
||||
m_samplingInterval = interval;
|
||||
}
|
||||
|
||||
Time
|
||||
RvBatteryModel::GetSamplingInterval (void) const
|
||||
{
|
||||
return m_samplingInterval;
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetOpenCircuitVoltage (double voltage)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << voltage);
|
||||
NS_ASSERT (voltage >= 0);
|
||||
m_openCircuitVoltage = voltage;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetOpenCircuitVoltage (void) const
|
||||
{
|
||||
return m_openCircuitVoltage;
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetCutoffVoltage (double voltage)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << voltage);
|
||||
NS_ASSERT (voltage <= m_openCircuitVoltage);
|
||||
m_cutoffVoltage = voltage;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetCutoffVoltage (void) const
|
||||
{
|
||||
return m_cutoffVoltage;
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetAlpha (double alpha)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << alpha);
|
||||
NS_ASSERT (alpha >= 0);
|
||||
m_alpha = alpha;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetAlpha (void) const
|
||||
{
|
||||
return m_alpha;
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetBeta (double beta)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << beta);
|
||||
NS_ASSERT (beta >= 0);
|
||||
m_beta = beta;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetBeta (void) const
|
||||
{
|
||||
return m_beta;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::GetBatteryLevel (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
UpdateEnergySource ();
|
||||
return m_batteryLevel;
|
||||
}
|
||||
|
||||
Time
|
||||
RvBatteryModel::GetLifetime (void) const
|
||||
{
|
||||
return m_lifetime;
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::SetNumOfTerms (int num)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << num);
|
||||
m_numOfTerms = num;
|
||||
}
|
||||
|
||||
int
|
||||
RvBatteryModel::GetNumOfTerms (void) const
|
||||
{
|
||||
return m_numOfTerms;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private functions start here.
|
||||
*/
|
||||
|
||||
void
|
||||
RvBatteryModel::DoStart (void)
|
||||
{
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Starting battery level update!");
|
||||
UpdateEnergySource (); // start periodic sampling of load (total current)
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::DoDispose (void)
|
||||
{
|
||||
BreakDeviceEnergyModelRefCycle (); // break reference cycle
|
||||
}
|
||||
|
||||
void
|
||||
RvBatteryModel::HandleEnergyDrainedEvent (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_DEBUG ("RvBatteryModel:Energy depleted!");
|
||||
NotifyEnergyDrained (); // notify DeviceEnergyModel objects
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::Discharge (double load, Time t)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << load << t);
|
||||
|
||||
// record only when load changes
|
||||
if (load != m_previousLoad)
|
||||
{
|
||||
m_load.push_back (load);
|
||||
m_previousLoad = load;
|
||||
if (t != Seconds (0.0))
|
||||
{
|
||||
m_timeStamps[m_timeStamps.size () - 1] = m_lastSampleTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_timeStamps.push_back (Seconds (0.0));
|
||||
}
|
||||
m_timeStamps.push_back (t);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_timeStamps[m_timeStamps.size () - 1] = t;
|
||||
}
|
||||
|
||||
m_lastSampleTime = t;
|
||||
|
||||
// calculate alpha for new t
|
||||
NS_ASSERT (m_load.size () == m_timeStamps.size () - 1); // size must be equal
|
||||
double calculatedAlpha = 0.0;
|
||||
if (m_timeStamps.size () == 1)
|
||||
{
|
||||
// constant load
|
||||
calculatedAlpha = m_load[0] * RvModelAFunction (t, t, Seconds(0.0),
|
||||
m_beta);
|
||||
}
|
||||
else
|
||||
{
|
||||
// changing load
|
||||
for (uint64_t i = 1; i < m_timeStamps.size (); i++)
|
||||
{
|
||||
calculatedAlpha += m_load[i - 1] * RvModelAFunction (t, m_timeStamps[i],
|
||||
m_timeStamps[i - 1],
|
||||
m_beta);
|
||||
}
|
||||
}
|
||||
|
||||
return calculatedAlpha;
|
||||
}
|
||||
|
||||
double
|
||||
RvBatteryModel::RvModelAFunction (Time t, Time sk, Time sk_1, double beta)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << t << sk << sk_1 << beta);
|
||||
|
||||
// everything is in minutes
|
||||
double firstDelta = (t.GetSeconds () - sk.GetSeconds ()) / 60;
|
||||
double secondDelta = (t.GetSeconds () - sk_1.GetSeconds ()) / 60;
|
||||
double delta = (sk.GetSeconds () - sk_1.GetSeconds ()) / 60;
|
||||
|
||||
double sum = 0.0;
|
||||
for (int m = 1; m <= m_numOfTerms; m++)
|
||||
{
|
||||
double square = beta * beta * m * m;
|
||||
sum += (exp (- square * (firstDelta)) - exp (- square * (secondDelta))) / square;
|
||||
}
|
||||
return delta + 2 * sum;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -0,0 +1,259 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Authors: Sidharth Nabar <snabar@uw.edu>, He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#ifndef RV_BATTERY_MODEL_H
|
||||
#define RV_BATTERY_MODEL_H
|
||||
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "energy-source.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Rakhmatov Vrudhula non-linear battery model.
|
||||
*
|
||||
* This (energy source) model implements an analytical non-linear battery model.
|
||||
* It is capable of capturing load capacity and recovery effects of batteries.
|
||||
* Batteries are characterized by 2 parameters, alpha and beta, which can both
|
||||
* be obtained from the discharge curve of the batteries.
|
||||
*
|
||||
* The model is developed by Daler Rakhmatov & Sarma Vrudhula in: "Battery
|
||||
* Lifetime Prediction for Energy-Aware Computing" and "An Analytical High-Level
|
||||
* Battery Model for Use in Energy Management of Portable Electronic Systems".
|
||||
*
|
||||
* The real-time algorithm is developed by Matthias Handy & Dirk Timmermann in:
|
||||
* "Simulation of Mobile Wireless Networks with Accurate Modeling of non-linear
|
||||
* battery effects". The real-time algorithm is modified by the authors of this
|
||||
* code for improved accuracy and reduced computation (sampling) overhead.
|
||||
*/
|
||||
class RvBatteryModel : public EnergySource
|
||||
{
|
||||
public:
|
||||
static TypeId GetTypeId (void);
|
||||
RvBatteryModel ();
|
||||
virtual ~RvBatteryModel ();
|
||||
|
||||
/**
|
||||
* \return Initial energy stored (theoretical capacity) in the battery.
|
||||
*
|
||||
* Implements GetInitialEnergy.
|
||||
*/
|
||||
virtual double GetInitialEnergy (void) const;
|
||||
|
||||
/**
|
||||
* \returns Supply voltage at the energy source.
|
||||
*
|
||||
* Implements GetSupplyVoltage.
|
||||
*/
|
||||
virtual double GetSupplyVoltage (void) const;
|
||||
|
||||
/**
|
||||
* \return Remaining energy in energy source, in Joules
|
||||
*
|
||||
* Implements GetRemainingEnergy.
|
||||
*/
|
||||
virtual double GetRemainingEnergy (void);
|
||||
|
||||
/**
|
||||
* \returns Energy fraction.
|
||||
*
|
||||
* Implements GetEnergyFraction. For the RV battery model, energy fraction is
|
||||
* equivalent to battery level.
|
||||
*/
|
||||
virtual double GetEnergyFraction (void);
|
||||
|
||||
/**
|
||||
* Implements UpdateEnergySource. This function samples the total load (total
|
||||
* current) from all devices to discharge the battery.
|
||||
*/
|
||||
virtual void UpdateEnergySource (void);
|
||||
|
||||
/**
|
||||
* \param interval Energy update interval.
|
||||
*
|
||||
* This function sets the interval between each energy update.
|
||||
*/
|
||||
void SetSamplingInterval (Time interval);
|
||||
|
||||
/**
|
||||
* \returns The interval between each energy update.
|
||||
*/
|
||||
Time GetSamplingInterval (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets open circuit voltage of battery.
|
||||
*
|
||||
* \param voltage Open circuit voltage.
|
||||
*/
|
||||
void SetOpenCircuitVoltage (double voltage);
|
||||
|
||||
/**
|
||||
* \return Open circuit voltage of battery.
|
||||
*/
|
||||
double GetOpenCircuitVoltage (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets cutoff voltage of battery.
|
||||
*
|
||||
* \param voltage Cutoff voltage.
|
||||
*/
|
||||
void SetCutoffVoltage (double voltage);
|
||||
|
||||
/**
|
||||
* \returns Cutoff voltage of battery.
|
||||
*/
|
||||
double GetCutoffVoltage (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets the alpha value for the battery model.
|
||||
*
|
||||
* \param alpha Alpha.
|
||||
*/
|
||||
void SetAlpha (double alpha);
|
||||
|
||||
/**
|
||||
* \returns The alpha value used by the battery model.
|
||||
*/
|
||||
double GetAlpha (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets the beta value for the battery model.
|
||||
*
|
||||
* \param beta Beta.
|
||||
*/
|
||||
void SetBeta (double beta);
|
||||
|
||||
/**
|
||||
* \returns The beta value used by the battery model.
|
||||
*/
|
||||
double GetBeta (void) const;
|
||||
|
||||
/**
|
||||
* \returns Battery level [0, 1].
|
||||
*/
|
||||
double GetBatteryLevel (void);
|
||||
|
||||
/**
|
||||
* \returns Lifetime of the battery.
|
||||
*/
|
||||
Time GetLifetime (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets the number of terms of the infinite sum for estimating battery
|
||||
* level.
|
||||
*
|
||||
* \param num Number of terms.
|
||||
*/
|
||||
void SetNumOfTerms (int num);
|
||||
|
||||
/**
|
||||
* \returns The number of terms of the infinite sum for estimating battery
|
||||
* level.
|
||||
*/
|
||||
int GetNumOfTerms (void) const;
|
||||
|
||||
private:
|
||||
/// Defined in ns3::Object
|
||||
virtual void DoStart (void);
|
||||
|
||||
/// Defined in ns3::Object
|
||||
virtual void DoDispose (void);
|
||||
|
||||
/**
|
||||
* Handles the remaining energy going to zero event. This function notifies
|
||||
* all the energy models aggregated to the node about the energy being
|
||||
* depleted. Each energy model is then responsible for its own handler.
|
||||
*/
|
||||
void HandleEnergyDrainedEvent (void);
|
||||
|
||||
/**
|
||||
* \brief Discharges the battery.
|
||||
*
|
||||
* \param load Load value (total current form devices, in mA).
|
||||
* \param t Time stamp of the load value.
|
||||
* \returns Calculated alpha value.
|
||||
*
|
||||
* Discharge function calculates a value which is then compared to the alpha
|
||||
* value to determine if the battery is dead. It will also update the battery
|
||||
* level.
|
||||
*
|
||||
* Note that the load value passed to Discharge has to be in mA.
|
||||
*/
|
||||
double Discharge (double load, Time t);
|
||||
|
||||
/**
|
||||
* \brief RV model A function.
|
||||
*
|
||||
* \param t Current time.
|
||||
* \param sk Time stamp in array position k
|
||||
* \param sk_1 Time stamp in array position k-1
|
||||
* \param beta Beta value used by the battery model.
|
||||
* \returns Result of A function.
|
||||
*
|
||||
* This function computes alpha value using the recorded load profile.
|
||||
*/
|
||||
double RvModelAFunction (Time t, Time sk, Time sk_1, double beta);
|
||||
|
||||
private:
|
||||
double m_openCircuitVoltage;
|
||||
double m_cutoffVoltage;
|
||||
double m_alpha; // alpha value of RV model, in Coulomb
|
||||
double m_beta; // beta value of RV model, in second^-1
|
||||
|
||||
double m_previousLoad; // load value (total current) of previous sampling
|
||||
std::vector<double> m_load; // load profile
|
||||
std::vector<Time> m_timeStamps; // time stamps of load profile
|
||||
Time m_lastSampleTime;
|
||||
uint64_t m_counter;
|
||||
|
||||
int m_numOfTerms; // # of terms for infinite sum in battery level estimation
|
||||
|
||||
/**
|
||||
* Battery level is defined as: output of Discharge function / alpha value
|
||||
*
|
||||
* The output of Discharge function is an estimated charge consumption of the
|
||||
* battery.
|
||||
*
|
||||
* The alpha value is the amount of charges stored in the battery, or battery
|
||||
* capacity (in Coulomb).
|
||||
*
|
||||
* When the battery is fully charged (no charge is consumed from the battery)
|
||||
* the battery level is 1. When the battery is fully discharged, the battery
|
||||
* level is 0.
|
||||
*
|
||||
* NOTE Note that the definition in Timmermann's paper is the inverse of this
|
||||
* definition. In the paper, battery level = 1 when the battery is drained.
|
||||
*/
|
||||
TracedValue<double> m_batteryLevel;
|
||||
|
||||
/**
|
||||
* (1 / sampling interval) = sampling frequency
|
||||
*/
|
||||
Time m_samplingInterval;
|
||||
EventId m_currentSampleEvent;
|
||||
|
||||
TracedValue<Time> m_lifetime; // time of death of the battery
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* RV_BATTERY_MODEL_H */
|
||||
@@ -37,6 +37,18 @@ WifiRadioEnergyModel::GetTypeId (void)
|
||||
static TypeId tid = TypeId ("ns3::WifiRadioEnergyModel")
|
||||
.SetParent<DeviceEnergyModel> ()
|
||||
.AddConstructor<WifiRadioEnergyModel> ()
|
||||
.AddAttribute ("IdleCurrentA",
|
||||
"The default radio Idle current in Ampere.",
|
||||
DoubleValue (0.000426), // idle mode = 426uA
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetIdleCurrentA,
|
||||
&WifiRadioEnergyModel::GetIdleCurrentA),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("CcaBusyCurrentA",
|
||||
"The default radio CCA Busy State current in Ampere.",
|
||||
DoubleValue (0.000426), // default to be the same as idle mode
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetCcaBusyCurrentA,
|
||||
&WifiRadioEnergyModel::GetCcaBusyCurrentA),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("TxCurrentA",
|
||||
"The radio Tx current in Ampere.",
|
||||
DoubleValue (0.0174), // transmit at 0dBm = 17.4mA
|
||||
@@ -49,17 +61,11 @@ WifiRadioEnergyModel::GetTypeId (void)
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetRxCurrentA,
|
||||
&WifiRadioEnergyModel::GetRxCurrentA),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("IdleCurrentA",
|
||||
"The default radio Idle current in Ampere.",
|
||||
DoubleValue (0.000426), // idle mode = 426uA
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetIdleCurrentA,
|
||||
&WifiRadioEnergyModel::GetIdleCurrentA),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddAttribute ("SleepCurrentA",
|
||||
"The default radio Sleep current in Ampere.",
|
||||
DoubleValue (0.00002), // power down mode = 20uA
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetSleepCurrentA,
|
||||
&WifiRadioEnergyModel::GetSleepCurrentA),
|
||||
.AddAttribute ("SwitchingCurrentA",
|
||||
"The default radio Channel Switch current in Ampere.",
|
||||
DoubleValue (0.000426), // default to be the same as idle mode
|
||||
MakeDoubleAccessor (&WifiRadioEnergyModel::SetSwitchingCurrentA,
|
||||
&WifiRadioEnergyModel::GetSwitchingCurrentA),
|
||||
MakeDoubleChecker<double> ())
|
||||
.AddTraceSource ("TotalEnergyConsumption",
|
||||
"Total energy consumption of the radio device.",
|
||||
@@ -71,29 +77,18 @@ WifiRadioEnergyModel::GetTypeId (void)
|
||||
WifiRadioEnergyModel::WifiRadioEnergyModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_currentState = IDLE; // initially IDLE
|
||||
m_currentState = WifiPhy::IDLE; // initially IDLE
|
||||
m_lastUpdateTime = Seconds (0.0);
|
||||
m_energyDepletionCallback.Nullify ();
|
||||
m_node = NULL;
|
||||
m_source = NULL;
|
||||
// set callback for WifiPhy listener
|
||||
m_listener = new WifiRadioEnergyModelPhyListener;
|
||||
m_listener->SetChangeStateCallback (MakeCallback (&DeviceEnergyModel::ChangeState, this));
|
||||
}
|
||||
|
||||
WifiRadioEnergyModel::~WifiRadioEnergyModel ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetNode (Ptr<Node> node)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << node);
|
||||
NS_ASSERT (node != NULL);
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
Ptr<Node>
|
||||
WifiRadioEnergyModel::GetNode (void) const
|
||||
{
|
||||
return m_node;
|
||||
delete m_listener;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -107,14 +102,38 @@ WifiRadioEnergyModel::SetEnergySource (Ptr<EnergySource> source)
|
||||
double
|
||||
WifiRadioEnergyModel::GetTotalEnergyConsumption (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_totalEnergyConsumption;
|
||||
}
|
||||
|
||||
double
|
||||
WifiRadioEnergyModel::GetIdleCurrentA (void) const
|
||||
{
|
||||
return m_idleCurrentA;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetIdleCurrentA (double idleCurrentA)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << idleCurrentA);
|
||||
m_idleCurrentA = idleCurrentA;
|
||||
}
|
||||
|
||||
double
|
||||
WifiRadioEnergyModel::GetCcaBusyCurrentA (void) const
|
||||
{
|
||||
return m_ccaBusyCurrentA;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetCcaBusyCurrentA (double CcaBusyCurrentA)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << CcaBusyCurrentA);
|
||||
m_ccaBusyCurrentA = CcaBusyCurrentA;
|
||||
}
|
||||
|
||||
double
|
||||
WifiRadioEnergyModel::GetTxCurrentA (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_txCurrentA;
|
||||
}
|
||||
|
||||
@@ -128,7 +147,6 @@ WifiRadioEnergyModel::SetTxCurrentA (double txCurrentA)
|
||||
double
|
||||
WifiRadioEnergyModel::GetRxCurrentA (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_rxCurrentA;
|
||||
}
|
||||
|
||||
@@ -140,37 +158,22 @@ WifiRadioEnergyModel::SetRxCurrentA (double rxCurrentA)
|
||||
}
|
||||
|
||||
double
|
||||
WifiRadioEnergyModel::GetIdleCurrentA (void) const
|
||||
WifiRadioEnergyModel::GetSwitchingCurrentA (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_idleCurrentA;
|
||||
return m_switchingCurrentA;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetIdleCurrentA (double idleCurrentA)
|
||||
WifiRadioEnergyModel::SetSwitchingCurrentA (double switchingCurrentA)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << idleCurrentA);
|
||||
m_idleCurrentA = idleCurrentA;
|
||||
NS_LOG_FUNCTION (this << switchingCurrentA);
|
||||
m_switchingCurrentA = switchingCurrentA;
|
||||
}
|
||||
|
||||
double
|
||||
WifiRadioEnergyModel::GetSleepCurrentA (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_sleepCurrentA;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetSleepCurrentA (double sleepCurrentA)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << sleepCurrentA);
|
||||
m_sleepCurrentA = sleepCurrentA;
|
||||
}
|
||||
|
||||
WifiRadioEnergyModel::WifiRadioState
|
||||
WifiPhy::State
|
||||
WifiRadioEnergyModel::GetCurrentState (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
return m_currentState;
|
||||
}
|
||||
|
||||
@@ -190,7 +193,6 @@ void
|
||||
WifiRadioEnergyModel::ChangeState (int newState)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << newState);
|
||||
NS_ASSERT (IsStateTransitionValid ((WifiRadioState) newState));
|
||||
|
||||
Time duration = Simulator::Now () - m_lastUpdateTime;
|
||||
NS_ASSERT (duration.GetNanoSeconds () >= 0); // check if duration is valid
|
||||
@@ -200,20 +202,23 @@ WifiRadioEnergyModel::ChangeState (int newState)
|
||||
double supplyVoltage = m_source->GetSupplyVoltage ();
|
||||
switch (m_currentState)
|
||||
{
|
||||
case TX:
|
||||
energyToDecrease = duration.GetSeconds () * m_txCurrentA * supplyVoltage;
|
||||
break;
|
||||
case RX:
|
||||
energyToDecrease = duration.GetSeconds () * m_rxCurrentA * supplyVoltage;
|
||||
break;
|
||||
case IDLE:
|
||||
case WifiPhy::IDLE:
|
||||
energyToDecrease = duration.GetSeconds () * m_idleCurrentA * supplyVoltage;
|
||||
break;
|
||||
case SLEEP:
|
||||
energyToDecrease = duration.GetSeconds () * m_sleepCurrentA * supplyVoltage;
|
||||
case WifiPhy::CCA_BUSY:
|
||||
energyToDecrease = duration.GetSeconds () * m_ccaBusyCurrentA * supplyVoltage;
|
||||
break;
|
||||
case WifiPhy::TX:
|
||||
energyToDecrease = duration.GetSeconds () * m_txCurrentA * supplyVoltage;
|
||||
break;
|
||||
case WifiPhy::RX:
|
||||
energyToDecrease = duration.GetSeconds () * m_rxCurrentA * supplyVoltage;
|
||||
break;
|
||||
case WifiPhy::SWITCHING:
|
||||
energyToDecrease = duration.GetSeconds () * m_switchingCurrentA * supplyVoltage;
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state!");
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state: " << m_currentState);
|
||||
}
|
||||
|
||||
// update total energy consumption
|
||||
@@ -226,19 +231,17 @@ WifiRadioEnergyModel::ChangeState (int newState)
|
||||
m_source->UpdateEnergySource ();
|
||||
|
||||
// update current state & last update time stamp
|
||||
SetWifiRadioState ((WifiRadioState) newState);
|
||||
SetWifiRadioState ((WifiPhy::State) newState);
|
||||
|
||||
// some debug message
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Total energy consumption at node #"
|
||||
<< m_node->GetId () << " is " << m_totalEnergyConsumption << "J");
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Total energy consumption is " <<
|
||||
m_totalEnergyConsumption << "J");
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::HandleEnergyDepletion (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Energy is depleted at node #" <<
|
||||
m_node->GetId ());
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Energy is depleted!");
|
||||
// invoke energy depletion callback, if set.
|
||||
if (!m_energyDepletionCallback.IsNull ())
|
||||
{
|
||||
@@ -246,6 +249,12 @@ WifiRadioEnergyModel::HandleEnergyDepletion (void)
|
||||
}
|
||||
}
|
||||
|
||||
WifiRadioEnergyModelPhyListener *
|
||||
WifiRadioEnergyModel::GetPhyListener (void)
|
||||
{
|
||||
return m_listener;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private functions start here.
|
||||
*/
|
||||
@@ -253,8 +262,6 @@ WifiRadioEnergyModel::HandleEnergyDepletion (void)
|
||||
void
|
||||
WifiRadioEnergyModel::DoDispose (void)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
m_node = NULL;
|
||||
m_source = NULL;
|
||||
m_energyDepletionCallback.Nullify ();
|
||||
}
|
||||
@@ -262,67 +269,151 @@ WifiRadioEnergyModel::DoDispose (void)
|
||||
double
|
||||
WifiRadioEnergyModel::DoGetCurrentA (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
switch (m_currentState)
|
||||
{
|
||||
case TX:
|
||||
return m_txCurrentA;
|
||||
case RX:
|
||||
return m_rxCurrentA;
|
||||
case IDLE:
|
||||
case WifiPhy::IDLE:
|
||||
return m_idleCurrentA;
|
||||
case SLEEP:
|
||||
return m_sleepCurrentA;
|
||||
case WifiPhy::CCA_BUSY:
|
||||
return m_ccaBusyCurrentA;
|
||||
case WifiPhy::TX:
|
||||
return m_txCurrentA;
|
||||
case WifiPhy::RX:
|
||||
return m_rxCurrentA;
|
||||
case WifiPhy::SWITCHING:
|
||||
return m_switchingCurrentA;
|
||||
default:
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state!");
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModel:Undefined radio state:" << m_currentState);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WifiRadioEnergyModel::IsStateTransitionValid (const WifiRadioState destState)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << destState);
|
||||
|
||||
/*
|
||||
* This is a placeholder function to specify if some of the radio state
|
||||
* transitions are prohibited. For example, if transition TX -> RX is not
|
||||
* allowed, and must go through IDLE as TX -> IDLE -> RX, then this method
|
||||
* can be used to raise an ns3 error.
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModel::SetWifiRadioState (const WifiRadioState state)
|
||||
WifiRadioEnergyModel::SetWifiRadioState (const WifiPhy::State state)
|
||||
{
|
||||
NS_LOG_FUNCTION (this);
|
||||
if (IsStateTransitionValid (state))
|
||||
NS_LOG_FUNCTION (this << state);
|
||||
m_currentState = state;
|
||||
std::string stateName;
|
||||
switch (state)
|
||||
{
|
||||
m_currentState = state;
|
||||
std::string stateName;
|
||||
switch (state)
|
||||
{
|
||||
case TX:
|
||||
stateName = "TX";
|
||||
break;
|
||||
case RX:
|
||||
stateName = "RX";
|
||||
break;
|
||||
case IDLE:
|
||||
stateName = "IDLE";
|
||||
break;
|
||||
case SLEEP:
|
||||
stateName = "SLEEP";
|
||||
break;
|
||||
}
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Switching to state: " << stateName <<
|
||||
" at time = " << Simulator::Now ());
|
||||
case WifiPhy::IDLE:
|
||||
stateName = "IDLE";
|
||||
break;
|
||||
case WifiPhy::CCA_BUSY:
|
||||
stateName = "CCA_BUSY";
|
||||
break;
|
||||
case WifiPhy::TX:
|
||||
stateName = "TX";
|
||||
break;
|
||||
case WifiPhy::RX:
|
||||
stateName = "RX";
|
||||
break;
|
||||
case WifiPhy::SWITCHING:
|
||||
stateName = "SWITCHING";
|
||||
break;
|
||||
}
|
||||
else
|
||||
NS_LOG_DEBUG ("WifiRadioEnergyModel:Switching to state: " << stateName <<
|
||||
" at time = " << Simulator::Now ());
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
WifiRadioEnergyModelPhyListener::WifiRadioEnergyModelPhyListener ()
|
||||
{
|
||||
m_changeStateCallback.Nullify ();
|
||||
}
|
||||
|
||||
WifiRadioEnergyModelPhyListener::~WifiRadioEnergyModelPhyListener ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::SetChangeStateCallback (DeviceEnergyModel::ChangeStateCallback callback)
|
||||
{
|
||||
NS_ASSERT (!callback.IsNull ());
|
||||
m_changeStateCallback = callback;
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifyRxStart (Time duration)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModel:Invalid state transition!");
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::RX);
|
||||
m_switchToIdleEvent.Cancel ();
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifyRxEndOk (void)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifyRxEndError (void)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::IDLE);
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifyTxStart (Time duration)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::TX);
|
||||
// schedule changing state back to IDLE after TX duration
|
||||
m_switchToIdleEvent.Cancel ();
|
||||
m_switchToIdleEvent = Simulator::Schedule (duration, &WifiRadioEnergyModelPhyListener::SwitchToIdle, this);
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifyMaybeCcaBusyStart (Time duration)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::CCA_BUSY);
|
||||
// schedule changing state back to IDLE after CCA_BUSY duration
|
||||
m_switchToIdleEvent.Cancel ();
|
||||
m_switchToIdleEvent = Simulator::Schedule (duration, &WifiRadioEnergyModelPhyListener::SwitchToIdle, this);
|
||||
}
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::NotifySwitchingStart (Time duration)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::SWITCHING);
|
||||
// schedule changing state back to IDLE after CCA_BUSY duration
|
||||
m_switchToIdleEvent.Cancel ();
|
||||
m_switchToIdleEvent = Simulator::Schedule (duration, &WifiRadioEnergyModelPhyListener::SwitchToIdle, this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private function state here.
|
||||
*/
|
||||
|
||||
void
|
||||
WifiRadioEnergyModelPhyListener::SwitchToIdle (void)
|
||||
{
|
||||
if (m_changeStateCallback.IsNull ())
|
||||
{
|
||||
NS_FATAL_ERROR ("WifiRadioEnergyModelPhyListener:Change state callback not set!");
|
||||
}
|
||||
m_changeStateCallback (WifiPhy::IDLE);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
@@ -25,9 +25,98 @@
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/event-id.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/wifi-phy.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* A WifiPhy listener class for notifying the WifiRadioEnergyModel of Wifi radio
|
||||
* state change.
|
||||
*/
|
||||
class WifiRadioEnergyModelPhyListener : public WifiPhyListener
|
||||
{
|
||||
public:
|
||||
WifiRadioEnergyModelPhyListener ();
|
||||
virtual ~WifiRadioEnergyModelPhyListener ();
|
||||
|
||||
/**
|
||||
* \brief Sets the change state callback. Used by helper class.
|
||||
*
|
||||
* \param callback Change state callback.
|
||||
*/
|
||||
void SetChangeStateCallback (DeviceEnergyModel::ChangeStateCallback callback);
|
||||
|
||||
/**
|
||||
* \brief Switches the WifiRadioEnergyModel to RX state.
|
||||
*
|
||||
* \param duration the expected duration of the packet reception.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*/
|
||||
virtual void NotifyRxStart (Time duration);
|
||||
|
||||
/**
|
||||
* \brief Switches the WifiRadioEnergyModel back to IDLE state.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*
|
||||
* Note that for the WifiRadioEnergyModel, the behavior of the function is the
|
||||
* same as NotifyRxEndError.
|
||||
*/
|
||||
virtual void NotifyRxEndOk (void);
|
||||
|
||||
/**
|
||||
* \brief Switches the WifiRadioEnergyModel back to IDLE state.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*
|
||||
* Note that for the WifiRadioEnergyModel, the behavior of the function is the
|
||||
* same as NotifyRxEndOk.
|
||||
*/
|
||||
virtual void NotifyRxEndError (void);
|
||||
|
||||
/**
|
||||
* \brief Switches the WifiRadioEnergyModel to TX state and switches back to
|
||||
* IDLE after TX duration.
|
||||
*
|
||||
* \param duration the expected transmission duration.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*/
|
||||
virtual void NotifyTxStart (Time duration);
|
||||
|
||||
/**
|
||||
* \param duration the expected busy duration.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*/
|
||||
virtual void NotifyMaybeCcaBusyStart (Time duration);
|
||||
|
||||
/**
|
||||
* \param duration the expected channel switching duration.
|
||||
*
|
||||
* Defined in ns3::WifiPhyListener
|
||||
*/
|
||||
virtual void NotifySwitchingStart (Time duration);
|
||||
|
||||
private:
|
||||
/**
|
||||
* A helper function that makes scheduling m_changeStateCallback possible.
|
||||
*/
|
||||
void SwitchToIdle (void);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Change state callback used to notify the WifiRadioEnergyModel of a state
|
||||
* change.
|
||||
*/
|
||||
DeviceEnergyModel::ChangeStateCallback m_changeStateCallback;
|
||||
|
||||
EventId m_switchToIdleEvent;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* \brief A WiFi radio energy model.
|
||||
*
|
||||
@@ -53,29 +142,6 @@ namespace ns3 {
|
||||
class WifiRadioEnergyModel : public DeviceEnergyModel
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Wifi radio states.
|
||||
*/
|
||||
enum WifiRadioState
|
||||
{
|
||||
/**
|
||||
* Radio is transmitting.
|
||||
*/
|
||||
TX = 0,
|
||||
/**
|
||||
* Radio is receiving.
|
||||
*/
|
||||
RX,
|
||||
/**
|
||||
* Radio is idling.
|
||||
*/
|
||||
IDLE,
|
||||
/**
|
||||
* Radio is asleep.
|
||||
*/
|
||||
SLEEP
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback type for energy depletion handling.
|
||||
*/
|
||||
@@ -86,24 +152,6 @@ public:
|
||||
WifiRadioEnergyModel ();
|
||||
virtual ~WifiRadioEnergyModel ();
|
||||
|
||||
/**
|
||||
* \brief Sets pointer to node.
|
||||
*
|
||||
* \param node Pointer to node.
|
||||
*
|
||||
* Implements DeviceEnergyModel::SetNode.
|
||||
*/
|
||||
virtual void SetNode (Ptr<Node> node);
|
||||
|
||||
/**
|
||||
* \brief Gets pointer to node.
|
||||
*
|
||||
* \returns Pointer to node.
|
||||
*
|
||||
* Implements DeviceEnergyModel::GetNode.
|
||||
*/
|
||||
virtual Ptr<Node> GetNode (void) const;
|
||||
|
||||
/**
|
||||
* \brief Sets pointer to EnergySouce installed on node.
|
||||
*
|
||||
@@ -121,19 +169,21 @@ public:
|
||||
virtual double GetTotalEnergyConsumption (void) const;
|
||||
|
||||
// Setter & getters for state power consumption.
|
||||
double GetIdleCurrentA (void) const;
|
||||
void SetIdleCurrentA (double idleCurrentA);
|
||||
double GetCcaBusyCurrentA (void) const;
|
||||
void SetCcaBusyCurrentA (double ccaBusyCurrentA);
|
||||
double GetTxCurrentA (void) const;
|
||||
void SetTxCurrentA (double txCurrentA);
|
||||
double GetRxCurrentA (void) const;
|
||||
void SetRxCurrentA (double rxCurrentA);
|
||||
double GetIdleCurrentA (void) const;
|
||||
void SetIdleCurrentA (double idleCurrentA);
|
||||
double GetSleepCurrentA (void) const;
|
||||
void SetSleepCurrentA (double sleepCurrentA);
|
||||
double GetSwitchingCurrentA (void) const;
|
||||
void SetSwitchingCurrentA (double switchingCurrentA);
|
||||
|
||||
/**
|
||||
* \returns Current state.
|
||||
*/
|
||||
WifiRadioState GetCurrentState (void) const;
|
||||
WifiPhy::State GetCurrentState (void) const;
|
||||
|
||||
/**
|
||||
* \param callback Callback function.
|
||||
@@ -158,6 +208,11 @@ public:
|
||||
*/
|
||||
virtual void HandleEnergyDepletion (void);
|
||||
|
||||
/**
|
||||
* \returns Pointer to the PHY listener.
|
||||
*/
|
||||
WifiRadioEnergyModelPhyListener * GetPhyListener (void);
|
||||
|
||||
|
||||
private:
|
||||
void DoDispose (void);
|
||||
@@ -169,41 +224,36 @@ private:
|
||||
*/
|
||||
virtual double DoGetCurrentA (void) const;
|
||||
|
||||
/**
|
||||
* \param destState Radio state to switch to.
|
||||
* \return True if the transition is allowed.
|
||||
*
|
||||
* This function checks if a given radio state transition is allowed.
|
||||
*/
|
||||
bool IsStateTransitionValid (const WifiRadioState destState);
|
||||
|
||||
/**
|
||||
* \param currentState New state the radio device is currently in.
|
||||
*
|
||||
* Sets current state. This function is private so that only the energy model
|
||||
* can change its own state.
|
||||
*/
|
||||
void SetWifiRadioState (const WifiRadioState state);
|
||||
void SetWifiRadioState (const WifiPhy::State state);
|
||||
|
||||
private:
|
||||
Ptr<Node> m_node;
|
||||
Ptr<EnergySource> m_source;
|
||||
|
||||
// Member variables for current draw in different radio modes.
|
||||
double m_txCurrentA;
|
||||
double m_rxCurrentA;
|
||||
double m_idleCurrentA;
|
||||
double m_sleepCurrentA;
|
||||
double m_ccaBusyCurrentA;
|
||||
double m_switchingCurrentA;
|
||||
|
||||
// This variable keeps track of the total energy consumed by this model.
|
||||
TracedValue<double> m_totalEnergyConsumption;
|
||||
|
||||
// State variables.
|
||||
WifiRadioState m_currentState; // current state the radio is in
|
||||
WifiPhy::State m_currentState; // current state the radio is in
|
||||
Time m_lastUpdateTime; // time stamp of previous energy update
|
||||
|
||||
// energy depletion callback
|
||||
// Energy depletion callback
|
||||
WifiRadioEnergyDepletionCallback m_energyDepletionCallback;
|
||||
|
||||
// WifiPhy listener
|
||||
WifiRadioEnergyModelPhyListener *m_listener;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Authors: He Wu <mdzz@u.washington.edu>
|
||||
* Author: He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#include "ns3/basic-energy-source.h"
|
||||
@@ -59,7 +59,7 @@ private:
|
||||
* Runs simulation for a while, check if final state & remaining energy is
|
||||
* correctly updated.
|
||||
*/
|
||||
bool StateSwitchTest (WifiRadioEnergyModel::WifiRadioState state);
|
||||
bool StateSwitchTest (WifiPhy::State state);
|
||||
|
||||
private:
|
||||
double m_timeS; // in seconds
|
||||
@@ -88,19 +88,23 @@ BasicEnergyUpdateTest::DoRun (void)
|
||||
m_deviceEnergyModel.SetTypeId ("ns3::WifiRadioEnergyModel");
|
||||
|
||||
// run state switch tests
|
||||
if (StateSwitchTest (WifiRadioEnergyModel::TX))
|
||||
if (StateSwitchTest (WifiPhy::IDLE))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (StateSwitchTest (WifiRadioEnergyModel::RX))
|
||||
if (StateSwitchTest (WifiPhy::CCA_BUSY))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (StateSwitchTest (WifiRadioEnergyModel::IDLE))
|
||||
if (StateSwitchTest (WifiPhy::TX))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (StateSwitchTest (WifiRadioEnergyModel::SLEEP))
|
||||
if (StateSwitchTest (WifiPhy::RX))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (StateSwitchTest (WifiPhy::SWITCHING))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -110,8 +114,7 @@ BasicEnergyUpdateTest::DoRun (void)
|
||||
}
|
||||
|
||||
bool
|
||||
BasicEnergyUpdateTest::StateSwitchTest (
|
||||
WifiRadioEnergyModel::WifiRadioState state)
|
||||
BasicEnergyUpdateTest::StateSwitchTest (WifiPhy::State state)
|
||||
{
|
||||
// create node
|
||||
Ptr<Node> node = CreateObject<Node> ();
|
||||
@@ -120,8 +123,6 @@ BasicEnergyUpdateTest::StateSwitchTest (
|
||||
Ptr<BasicEnergySource> source = m_energySource.Create<BasicEnergySource> ();
|
||||
// aggregate energy source to node
|
||||
node->AggregateObject (source);
|
||||
// set update interval in source
|
||||
source->SetEnergyUpdateInterval (Seconds (1.0));
|
||||
|
||||
// create device energy model
|
||||
Ptr<WifiRadioEnergyModel> model =
|
||||
@@ -176,17 +177,20 @@ BasicEnergyUpdateTest::StateSwitchTest (
|
||||
double current = 0.0;
|
||||
switch (state)
|
||||
{
|
||||
case WifiRadioEnergyModel::TX:
|
||||
current = devModel->GetTxCurrentA ();
|
||||
break;
|
||||
case WifiRadioEnergyModel::RX:
|
||||
current = devModel->GetRxCurrentA ();
|
||||
break;
|
||||
case WifiRadioEnergyModel::IDLE:
|
||||
case WifiPhy::IDLE:
|
||||
current = devModel->GetIdleCurrentA ();
|
||||
break;
|
||||
case WifiRadioEnergyModel::SLEEP:
|
||||
current = devModel->GetSleepCurrentA ();
|
||||
case WifiPhy::CCA_BUSY:
|
||||
current = devModel->GetCcaBusyCurrentA ();
|
||||
break;
|
||||
case WifiPhy::TX:
|
||||
current = devModel->GetTxCurrentA ();
|
||||
break;
|
||||
case WifiPhy::RX:
|
||||
current = devModel->GetRxCurrentA ();
|
||||
break;
|
||||
case WifiPhy::SWITCHING:
|
||||
current = devModel->GetSwitchingCurrentA ();
|
||||
break;
|
||||
default:
|
||||
NS_FATAL_ERROR ("Undefined radio state: " << state);
|
||||
@@ -204,7 +208,7 @@ BasicEnergyUpdateTest::StateSwitchTest (
|
||||
"Incorrect remaining energy!");
|
||||
|
||||
// obtain radio state
|
||||
WifiRadioEnergyModel::WifiRadioState endState = devModel->GetCurrentState ();
|
||||
WifiPhy::State endState = devModel->GetCurrentState ();
|
||||
NS_LOG_UNCOND ("Radio state is " << endState);
|
||||
// check end state
|
||||
NS_TEST_ASSERT_MSG_EQ (endState, state, "Incorrect end state!");
|
||||
@@ -362,8 +366,7 @@ BasicEnergyDepletionTest::DepletionTestCase (double simTimeS,
|
||||
MakeCallback (&BasicEnergyDepletionTest::DepletionHandler, this);
|
||||
radioEnergyHelper.SetDepletionCallback (callback);
|
||||
// install on node
|
||||
DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices,
|
||||
sources);
|
||||
DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
|
||||
|
||||
// run simulation
|
||||
Simulator::Stop (Seconds (simTimeS));
|
||||
@@ -376,8 +379,7 @@ BasicEnergyDepletionTest::DepletionTestCase (double simTimeS,
|
||||
NS_LOG_UNCOND ("Actual callback count is " << m_callbackCount);
|
||||
|
||||
// check result, call back should only be invoked once
|
||||
NS_TEST_ASSERT_MSG_EQ (m_numOfNodes, m_callbackCount,
|
||||
"Not all callbacks are invoked!");
|
||||
NS_TEST_ASSERT_MSG_EQ (m_numOfNodes, m_callbackCount, "Not all callbacks are invoked!");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -399,7 +401,7 @@ BasicEnergyModelTestSuite::BasicEnergyModelTestSuite ()
|
||||
: TestSuite ("basic-energy-model", UNIT)
|
||||
{
|
||||
AddTestCase (new BasicEnergyUpdateTest);
|
||||
//AddTestCase (new BasicEnergyDepletionTest);
|
||||
AddTestCase (new BasicEnergyDepletionTest);
|
||||
}
|
||||
|
||||
// create an instance of the test suite
|
||||
|
||||
@@ -0,0 +1,906 @@
|
||||
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
|
||||
*
|
||||
* 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: He Wu <mdzz@u.washington.edu>
|
||||
*/
|
||||
|
||||
#include "ns3/rv-battery-model.h"
|
||||
#include "ns3/wifi-radio-energy-model.h"
|
||||
#include "ns3/rv-battery-model-helper.h"
|
||||
#include "ns3/wifi-radio-energy-model-helper.h"
|
||||
#include "ns3/energy-source-container.h"
|
||||
#include "ns3/device-energy-model-container.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/double.h"
|
||||
#include "ns3/config.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/yans-wifi-helper.h"
|
||||
#include "ns3/nqos-wifi-mac-helper.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("RvBatteryModelTestSuite");
|
||||
|
||||
/**
|
||||
* Test case of update remaining energy for RvBatteryModel and
|
||||
* WifiRadioEnergyModel.
|
||||
*/
|
||||
class BatteryLifetimeTest : public TestCase
|
||||
{
|
||||
public:
|
||||
BatteryLifetimeTest ();
|
||||
virtual ~BatteryLifetimeTest ();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Creates load profiles according to "Battery Lifetime Prediction for Energy-
|
||||
* Aware Computing" paper.
|
||||
*/
|
||||
void CreateLoadProfiles (void);
|
||||
|
||||
/**
|
||||
* \returns False if no error occurs.
|
||||
*
|
||||
* Runs test.
|
||||
*/
|
||||
bool DoRun (void);
|
||||
|
||||
/**
|
||||
* \param load Load value, in Amperes (A).
|
||||
* \param expLifetime Expected lifetime.
|
||||
* \return False if no error occurs.
|
||||
*
|
||||
* Runs simulation with constant load and checks the battery lifetime with
|
||||
* known results.
|
||||
*/
|
||||
bool ConstantLoadTest (double load, Time expLifetime);
|
||||
|
||||
/**
|
||||
* \param loads Load profile.
|
||||
* \param timeStamps Time stamps.
|
||||
* \param expLifeTime Expected lifetime.
|
||||
* \returns False if no error occurs.
|
||||
*
|
||||
* Runs simulation with variable load and checks the battery lifetime with
|
||||
* known results.
|
||||
*/
|
||||
bool VariableLoadTest (std::vector<double> loads,
|
||||
std::vector<Time> timeStamps,
|
||||
Time expLifetime);
|
||||
|
||||
private:
|
||||
typedef struct LoadProfile
|
||||
{
|
||||
std::vector<double> loads;
|
||||
std::vector<Time> timeStamps;
|
||||
Time itsyLifetime;
|
||||
Time dualFoilLifeTime;
|
||||
} LoadProfile;
|
||||
|
||||
private:
|
||||
std::vector<LoadProfile> m_loadProfiles;
|
||||
double m_alpha;
|
||||
double m_beta;
|
||||
};
|
||||
|
||||
BatteryLifetimeTest::BatteryLifetimeTest ()
|
||||
: TestCase ("RV battery model battery lifetime test case.")
|
||||
{
|
||||
// Itsy battery
|
||||
m_alpha = 35220;
|
||||
m_beta = 0.637;
|
||||
}
|
||||
|
||||
BatteryLifetimeTest::~BatteryLifetimeTest ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BatteryLifetimeTest::CreateLoadProfiles (void)
|
||||
{
|
||||
// create set of load profiles
|
||||
LoadProfile profile;
|
||||
|
||||
std::vector<double> loads;
|
||||
std::vector<Time> timeStamps;
|
||||
|
||||
// C1
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (19.5 * 60));
|
||||
timeStamps.push_back (Seconds (26.0 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (55.0 * 60); // 55.0 minutes
|
||||
profile.dualFoilLifeTime = Seconds (36.2 * 60); // 36.2 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C2
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.4947);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (31.0 * 60));
|
||||
timeStamps.push_back (Seconds (41.3 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (73.9 * 60); // 73.9 minutes
|
||||
profile.dualFoilLifeTime = Seconds (55.8 * 60); // 55.8 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C3
|
||||
loads.push_back (0.4256);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.4256);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (41.0 * 60));
|
||||
timeStamps.push_back (Seconds (54.6 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (88.8 * 60); // 88.8 minutes
|
||||
profile.dualFoilLifeTime = Seconds (71.8 * 60); // 71.8 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C4
|
||||
loads.push_back (0.2923);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.2923);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (74.6 * 60));
|
||||
timeStamps.push_back (Seconds (99.5 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (137.8 * 60); // 137.8 minutes
|
||||
profile.dualFoilLifeTime = Seconds (124.9 * 60); // 124.9 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C5
|
||||
loads.push_back (0.2227);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (105.7 * 60));
|
||||
timeStamps.push_back (Seconds (140.9 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (185.8 * 60); // 185.8 minutes
|
||||
profile.dualFoilLifeTime = Seconds (176.7 * 60); // 176.7 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C6
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (19.5 * 60));
|
||||
timeStamps.push_back (Seconds (29.9 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (58.9 * 60); // 58.9 minutes
|
||||
profile.dualFoilLifeTime = Seconds (41.0 * 60); // 41.0 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C7
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (19.5 * 60));
|
||||
timeStamps.push_back (Seconds (22.1 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (51.1 * 60); // 51.1 minutes
|
||||
profile.dualFoilLifeTime = Seconds (30.8 * 60); // 30.8 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C8
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (23.4 * 60));
|
||||
timeStamps.push_back (Seconds (29.9 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (55.0 * 60); // 55.0 minutes
|
||||
profile.dualFoilLifeTime = Seconds (37.4 * 60); // 37.4 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C9
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (15.6 * 60));
|
||||
timeStamps.push_back (Seconds (22.1 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (55.0 * 60); // 55.0 minutes
|
||||
profile.dualFoilLifeTime = Seconds (35.2 * 60); // 35.2 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C10
|
||||
loads.push_back (0.300);
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.2523);
|
||||
loads.push_back (0.2341);
|
||||
loads.push_back (0.1379);
|
||||
loads.push_back (0.1139);
|
||||
loads.push_back (0.2656);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (0.5 * 60));
|
||||
timeStamps.push_back (Seconds (5.5 * 60));
|
||||
timeStamps.push_back (Seconds (10.5 * 60));
|
||||
timeStamps.push_back (Seconds (35.5 * 60));
|
||||
timeStamps.push_back (Seconds (60.5 * 60));
|
||||
timeStamps.push_back (Seconds (85.5 * 60));
|
||||
timeStamps.push_back (Seconds (110.5 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (144.3 * 60); // 144.3 minutes
|
||||
profile.dualFoilLifeTime = Seconds (132.6 * 60); // 132.6 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C11
|
||||
loads.push_back (0.300);
|
||||
loads.push_back (0.1139);
|
||||
loads.push_back (0.1379);
|
||||
loads.push_back (0.2341);
|
||||
loads.push_back (0.2523);
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0.2656);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (0.5 * 60));
|
||||
timeStamps.push_back (Seconds (25.5 * 60));
|
||||
timeStamps.push_back (Seconds (50.5 * 60));
|
||||
timeStamps.push_back (Seconds (75.5 * 60));
|
||||
timeStamps.push_back (Seconds (100.5 * 60));
|
||||
timeStamps.push_back (Seconds (105.5 * 60));
|
||||
timeStamps.push_back (Seconds (110.5 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (144.3 * 60); // 144.3 minutes
|
||||
profile.dualFoilLifeTime = Seconds (107.4 * 60); // 107.4 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C12
|
||||
loads.push_back (0.300);
|
||||
loads.push_back (0.1139);
|
||||
loads.push_back (0.1379);
|
||||
loads.push_back (0.2341);
|
||||
loads.push_back (0.2523);
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.0);
|
||||
loads.push_back (0.300);
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0.2656);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (0.5 * 60));
|
||||
timeStamps.push_back (Seconds (25.5 * 60));
|
||||
timeStamps.push_back (Seconds (50.5 * 60));
|
||||
timeStamps.push_back (Seconds (75.5 * 60));
|
||||
timeStamps.push_back (Seconds (100.5 * 60));
|
||||
timeStamps.push_back (Seconds (105.5 * 60));
|
||||
timeStamps.push_back (Seconds (130.5 * 60));
|
||||
timeStamps.push_back (Seconds (131.0 * 60));
|
||||
timeStamps.push_back (Seconds (136.0 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (169.3 * 60); // 169.3 minutes
|
||||
profile.dualFoilLifeTime = Seconds (155.4 * 60); // 155.4 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C13
|
||||
loads.push_back (0.300);
|
||||
timeStamps.push_back (Seconds (0));
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.2523);
|
||||
loads.push_back (0.2341);
|
||||
loads.push_back (0.1379);
|
||||
loads.push_back (0.1139);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((1.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((2.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((7.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((12.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((17.5 + i * 22.5) * 60));
|
||||
}
|
||||
|
||||
loads.push_back (0.2656);
|
||||
timeStamps.push_back (Seconds (110.5 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (144.3 * 60); // 144.3 minutes
|
||||
profile.dualFoilLifeTime = Seconds (131.7 * 60); // 131.7 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C14, time stamp calculation in paper is off, using our own estimated value
|
||||
loads.push_back (0.300);
|
||||
timeStamps.push_back (Seconds (0));
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
loads.push_back (0.1139);
|
||||
loads.push_back (0.1379);
|
||||
loads.push_back (0.2341);
|
||||
loads.push_back (0.2523);
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((5.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((10.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((15.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((20.5 + i * 22.5) * 60));
|
||||
timeStamps.push_back (Seconds ((21.5 + i * 22.5) * 60));
|
||||
}
|
||||
|
||||
loads.push_back (0.2656);
|
||||
timeStamps.push_back (Seconds (112.5 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (141.5 * 60); // 141.5 minutes
|
||||
profile.dualFoilLifeTime = Seconds (126.3 * 60); // 126.3 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C15
|
||||
loads.push_back (0.2227);
|
||||
loads.push_back (0.2045);
|
||||
loads.push_back (0.1083);
|
||||
loads.push_back (0.0843);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (50.0 * 60));
|
||||
timeStamps.push_back (Seconds (100.0 * 60));
|
||||
timeStamps.push_back (Seconds (150.0 * 60));
|
||||
timeStamps.push_back (Seconds (200.0 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (211.4 * 60); // 211.4 minutes
|
||||
profile.dualFoilLifeTime = Seconds (209.2 * 60); // 209.2 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C16
|
||||
loads.push_back (0.0843);
|
||||
loads.push_back (0.1083);
|
||||
loads.push_back (0.2045);
|
||||
loads.push_back (0.2227);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (50.0 * 60));
|
||||
timeStamps.push_back (Seconds (100.0 * 60));
|
||||
timeStamps.push_back (Seconds (150.0 * 60));
|
||||
timeStamps.push_back (Seconds (200.0 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (211.4 * 60); // 211.4 minutes
|
||||
profile.dualFoilLifeTime = Seconds (200.7 * 60); // 200.7 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C17
|
||||
loads.push_back (0.0843);
|
||||
loads.push_back (0.1083);
|
||||
loads.push_back (0.2045);
|
||||
loads.push_back (0.0);
|
||||
loads.push_back (0.2227);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds (0));
|
||||
timeStamps.push_back (Seconds (50.0 * 60));
|
||||
timeStamps.push_back (Seconds (100.0 * 60));
|
||||
timeStamps.push_back (Seconds (150.0 * 60));
|
||||
timeStamps.push_back (Seconds (200.0 * 60));
|
||||
timeStamps.push_back (Seconds (250.0 * 60));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (261.4 * 60); // 261.4 minutes
|
||||
profile.dualFoilLifeTime = Seconds (251.2 * 60); // 251.2 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C18
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
loads.push_back (0.0843);
|
||||
loads.push_back (0.1083);
|
||||
loads.push_back (0.2045);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((5.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((10.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((15.0 + i * 20.0) * 60));
|
||||
}
|
||||
|
||||
loads.push_back (0.2227);
|
||||
timeStamps.push_back (Seconds (200.0));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (211.4 * 60); // 211.4 minutes
|
||||
profile.dualFoilLifeTime = Seconds (204.6 * 60); // 204.6 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C19
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
loads.push_back (0.0755);
|
||||
loads.push_back (0.0949);
|
||||
loads.push_back (0.2045);
|
||||
loads.push_back (0.2227);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((5.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((10.0 + i * 20.0) * 60));
|
||||
timeStamps.push_back (Seconds ((15.0 + i * 20.0) * 60));
|
||||
}
|
||||
|
||||
loads.push_back (0.2227);
|
||||
timeStamps.push_back (Seconds (200.0));
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (216.4 * 60); // 216.4 minutes
|
||||
profile.dualFoilLifeTime = Seconds (208.7 * 60); // 208.7 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C20
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.628);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.0 + i * 2.0) * 60));
|
||||
timeStamps.push_back (Seconds ((1.0 + i * 2.0) * 60));
|
||||
}
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (55.3 * 60); // 55.3 minutes
|
||||
profile.dualFoilLifeTime = Seconds (33.2 * 60); // 33.2 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C21
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
loads.push_back (0.4947);
|
||||
loads.push_back (0.628);
|
||||
loads.push_back (0.0576);
|
||||
|
||||
timeStamps.push_back (Seconds ((0.0 + i * 3.0) * 60));
|
||||
timeStamps.push_back (Seconds ((1.0 + i * 3.0) * 60));
|
||||
timeStamps.push_back (Seconds ((2.0 + i * 3.0) * 60));
|
||||
}
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (79.6 * 60); // 79.6 minutes
|
||||
profile.dualFoilLifeTime = Seconds (55.9 * 60); // 55.9 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
|
||||
// C22
|
||||
for (int i = 0; i < 150; i++)
|
||||
{
|
||||
loads.push_back (0.005 + 0.005 * i);
|
||||
timeStamps.push_back (Seconds ((0.0 + i * 1.0) * 60));
|
||||
}
|
||||
|
||||
profile.loads = loads;
|
||||
profile.timeStamps = timeStamps;
|
||||
profile.itsyLifetime = Seconds (112.2 * 60); // 112.2 minutes
|
||||
profile.dualFoilLifeTime = Seconds (94.5 * 60); // 94.5 minutes
|
||||
|
||||
m_loadProfiles.push_back (profile);
|
||||
|
||||
loads.clear ();
|
||||
timeStamps.clear ();
|
||||
}
|
||||
|
||||
bool
|
||||
BatteryLifetimeTest::DoRun (void)
|
||||
{
|
||||
NS_LOG_UNCOND ("Constant load run.");
|
||||
// 640mA
|
||||
if (ConstantLoadTest (0.640, Seconds (2844.0)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 320mA
|
||||
if (ConstantLoadTest (0.320, Seconds (6146.0)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 128mA
|
||||
if (ConstantLoadTest (0.128, Seconds (16052.0)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 64mA
|
||||
if (ConstantLoadTest (0.064, Seconds (32561.0)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// 32mA
|
||||
if (ConstantLoadTest (0.032, Seconds (65580.0)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// create load profiles for variable load test
|
||||
CreateLoadProfiles ();
|
||||
|
||||
// variable load with Itsy battery
|
||||
NS_LOG_UNCOND ("\n\nItsy");
|
||||
m_alpha = 35220;
|
||||
m_beta = 0.637;
|
||||
for (uint32_t i = 0; i < m_loadProfiles.size (); i++)
|
||||
{
|
||||
NS_LOG_UNCOND ("========");
|
||||
NS_LOG_UNCOND ("Variable load profile C" << i + 1);
|
||||
if (VariableLoadTest (m_loadProfiles[i].loads,
|
||||
m_loadProfiles[i].timeStamps,
|
||||
m_loadProfiles[i].itsyLifetime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// variable load with DUALFOIL battery
|
||||
NS_LOG_UNCOND ("\n\nDUALFOIL");
|
||||
m_alpha = 40027;
|
||||
m_beta = 0.276;
|
||||
for (uint32_t i = 0; i < m_loadProfiles.size (); i++)
|
||||
{
|
||||
NS_LOG_UNCOND ("========");
|
||||
NS_LOG_UNCOND ("Variable load profile C" << i + 1);
|
||||
if (VariableLoadTest (m_loadProfiles[i].loads,
|
||||
m_loadProfiles[i].timeStamps,
|
||||
m_loadProfiles[i].dualFoilLifeTime))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // error free
|
||||
}
|
||||
|
||||
bool
|
||||
BatteryLifetimeTest::ConstantLoadTest (double load, Time expLifetime)
|
||||
{
|
||||
// create single node
|
||||
NodeContainer c;
|
||||
c.Create (1);
|
||||
|
||||
std::string phyMode ("DsssRate1Mbps");
|
||||
|
||||
// disable fragmentation for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
|
||||
StringValue ("2200"));
|
||||
// turn off RTS/CTS for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
|
||||
StringValue ("2200"));
|
||||
// Fix non-unicast data rate to be the same as that of unicast
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
|
||||
StringValue (phyMode));
|
||||
|
||||
// install YansWifiPhy
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
|
||||
|
||||
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
|
||||
/*
|
||||
* This is one parameter that matters when using FixedRssLossModel, set it to
|
||||
* zero; otherwise, gain will be added.
|
||||
*/
|
||||
wifiPhy.Set ("RxGain", DoubleValue (0));
|
||||
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
|
||||
wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
|
||||
|
||||
YansWifiChannelHelper wifiChannel ;
|
||||
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
wifiPhy.SetChannel (wifiChannel.Create ());
|
||||
|
||||
// Add a non-QoS upper MAC, and disable rate control
|
||||
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue(phyMode),
|
||||
"ControlMode", StringValue(phyMode));
|
||||
// Set it to ad-hoc mode
|
||||
wifiMac.SetType ("ns3::AdhocWifiMac");
|
||||
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
|
||||
|
||||
// Create and install battery model and device models
|
||||
// RV battery model
|
||||
RvBatteryModelHelper rvModelHelper;
|
||||
// Set alpha & beta values
|
||||
rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
|
||||
rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
|
||||
// install source
|
||||
EnergySourceContainer sources = rvModelHelper.Install (c);
|
||||
// device energy model
|
||||
WifiRadioEnergyModelHelper radioEnergyHelper;
|
||||
// set VariableLoadTestIDLE current, which will be the constant load
|
||||
radioEnergyHelper.Set ("IdleCurrentA", DoubleValue (load));
|
||||
// install on node
|
||||
DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
|
||||
|
||||
// run simulation
|
||||
Simulator::Stop (Seconds (70000.0));
|
||||
Simulator::Run ();
|
||||
|
||||
Time actualLifetime;
|
||||
Ptr<RvBatteryModel> srcPtr = DynamicCast<RvBatteryModel> (sources.Get (0));
|
||||
actualLifetime = srcPtr->GetLifetime ();
|
||||
|
||||
NS_LOG_UNCOND ("Expected lifetime = " << expLifetime.GetSeconds () << "s");
|
||||
NS_LOG_UNCOND ("Actual lifetime = " << actualLifetime.GetSeconds () << "s");
|
||||
|
||||
NS_TEST_ASSERT_MSG_EQ (actualLifetime, expLifetime, "Incorrect lifetime!");
|
||||
/*
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (actualLifetime.GetSeconds () / 60,
|
||||
expLifetime.GetSeconds () / 60, 0.1,
|
||||
"Incorrect lifetime!");
|
||||
*/
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return false; // error free
|
||||
}
|
||||
|
||||
bool
|
||||
BatteryLifetimeTest::VariableLoadTest (std::vector<double> loads,
|
||||
std::vector<Time> timeStamps,
|
||||
Time expLifetime)
|
||||
{
|
||||
NS_ASSERT (loads.size () == timeStamps.size ());
|
||||
|
||||
// create single node
|
||||
NodeContainer c;
|
||||
c.Create (1);
|
||||
|
||||
std::string phyMode ("DsssRate1Mbps");
|
||||
|
||||
// disable fragmentation for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
|
||||
StringValue ("2200"));
|
||||
// turn off RTS/CTS for frames below 2200 bytes
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
|
||||
StringValue ("2200"));
|
||||
// Fix non-unicast data rate to be the same as that of unicast
|
||||
Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
|
||||
StringValue (phyMode));
|
||||
|
||||
// install YansWifiPhy
|
||||
WifiHelper wifi;
|
||||
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
|
||||
|
||||
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
|
||||
/*
|
||||
* This is one parameter that matters when using FixedRssLossModel, set it to
|
||||
* zero; otherwise, gain will be added.
|
||||
*/
|
||||
wifiPhy.Set ("RxGain", DoubleValue (0));
|
||||
// ns-3 supports RadioTap and Prism tracing extensions for 802.11b
|
||||
wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
|
||||
|
||||
YansWifiChannelHelper wifiChannel ;
|
||||
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
|
||||
wifiPhy.SetChannel (wifiChannel.Create ());
|
||||
|
||||
// Add a non-QoS upper MAC, and disable rate control
|
||||
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
|
||||
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
|
||||
"DataMode", StringValue(phyMode),
|
||||
"ControlMode", StringValue(phyMode));
|
||||
// Set it to ad-hoc mode
|
||||
wifiMac.SetType ("ns3::AdhocWifiMac");
|
||||
NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
|
||||
|
||||
// Create and install battery model and device models
|
||||
// RV battery model
|
||||
RvBatteryModelHelper rvModelHelper;
|
||||
// Set alpha & beta values
|
||||
rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
|
||||
rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
|
||||
// install source
|
||||
EnergySourceContainer sources = rvModelHelper.Install (c);
|
||||
// device energy model
|
||||
WifiRadioEnergyModelHelper radioEnergyHelper;
|
||||
// set VariableLoadTestIDLE current, which will be the constant load
|
||||
radioEnergyHelper.Set ("IdleCurrentA", DoubleValue (loads[0]));
|
||||
// install on node
|
||||
DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
|
||||
|
||||
|
||||
Ptr<WifiRadioEnergyModel> wifiDevicePtr = DynamicCast<WifiRadioEnergyModel> (deviceModels.Get (0));
|
||||
// schedule load change events
|
||||
for (uint32_t i = 1; i < loads.size (); i++)
|
||||
{
|
||||
Simulator::Schedule (timeStamps[i], &WifiRadioEnergyModel::SetIdleCurrentA,
|
||||
wifiDevicePtr, loads[i]);
|
||||
}
|
||||
|
||||
// run simulation
|
||||
Simulator::Stop (Seconds (70000.0));
|
||||
Simulator::Run ();
|
||||
|
||||
Time actualLifetime;
|
||||
Ptr<RvBatteryModel> srcPtr = DynamicCast<RvBatteryModel> (sources.Get (0));
|
||||
actualLifetime = srcPtr->GetLifetime ();
|
||||
|
||||
NS_LOG_UNCOND ("Expected lifetime = " << expLifetime.GetSeconds () << "s");
|
||||
NS_LOG_UNCOND ("Actual lifetime = " << actualLifetime.GetSeconds () << "s");
|
||||
NS_LOG_UNCOND ("Difference = " << expLifetime.GetSeconds () - actualLifetime.GetSeconds () << "s");
|
||||
|
||||
//NS_TEST_ASSERT_MSG_EQ (actualLifetime, expLifetime, "Incorrect lifetime!");
|
||||
NS_TEST_ASSERT_MSG_EQ_TOL (actualLifetime.GetSeconds (), expLifetime.GetSeconds (),
|
||||
120, // error tolerance = 120s
|
||||
"Incorrect lifetime!");
|
||||
|
||||
Simulator::Destroy ();
|
||||
|
||||
return false; // error free
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------- //
|
||||
|
||||
/**
|
||||
* Unit test suite for energy model. Although the test suite involves 2 modules
|
||||
* it is still considered a unit test. Because a DeviceEnergyModel cannot live
|
||||
* without an EnergySource.
|
||||
*/
|
||||
class RvBatteryModelTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
RvBatteryModelTestSuite ();
|
||||
};
|
||||
|
||||
RvBatteryModelTestSuite::RvBatteryModelTestSuite ()
|
||||
: TestSuite ("rv-battery-model", SYSTEM)
|
||||
{
|
||||
AddTestCase (new BatteryLifetimeTest);
|
||||
}
|
||||
|
||||
// create an instance of the test suite
|
||||
RvBatteryModelTestSuite g_rvBatteryModelTestSuite;
|
||||
@@ -6,13 +6,16 @@ def build(bld):
|
||||
'model/wifi-radio-energy-model.cc',
|
||||
'model/energy-source.cc',
|
||||
'model/basic-energy-source.cc',
|
||||
'model/rv-battery-model.cc',
|
||||
'model/device-energy-model.cc',
|
||||
'model/device-energy-model-container.cc',
|
||||
'helper/energy-source-container.cc',
|
||||
'helper/energy-model-helper.cc',
|
||||
'helper/basic-energy-source-helper.cc',
|
||||
'helper/wifi-radio-energy-model-helper.cc',
|
||||
'helper/rv-battery-model-helper.cc',
|
||||
'test/basic-energy-model-test.cc',
|
||||
'test/rv-battery-model-test.cc',
|
||||
]
|
||||
headers = bld.new_task_gen('ns3header')
|
||||
headers.module = 'energy'
|
||||
@@ -20,10 +23,12 @@ def build(bld):
|
||||
'model/wifi-radio-energy-model.h',
|
||||
'model/energy-source.h',
|
||||
'model/basic-energy-source.h',
|
||||
'model/rv-battery-model.h',
|
||||
'model/device-energy-model.h',
|
||||
'model/device-energy-model-container.h',
|
||||
'helper/energy-source-container.h',
|
||||
'helper/energy-model-helper.h',
|
||||
'helper/basic-energy-source-helper.h',
|
||||
'helper/wifi-radio-energy-model-helper.h',
|
||||
'helper/rv-battery-model-helper.h',
|
||||
]
|
||||
@@ -102,6 +102,8 @@ example_tests = [
|
||||
("examples/emulation/emu-ping", "False", "True"),
|
||||
("examples/emulation/emu-udp-echo", "False", "True"),
|
||||
|
||||
("examples/energy/energy-model-example", "True", "True"),
|
||||
|
||||
("examples/error-model/simple-error-model", "True", "True"),
|
||||
|
||||
("examples/ipv6/icmpv6-redirect", "True", "True"),
|
||||
|
||||
Reference in new issue
Block a user