# HG changeset patch # User He Wu # Date 1292888952 28800 # Node ID d8909a1fd0ff2de298e9e5090711f9cec203fd50 # Parent bc947fbfac8051a70745455b1deb33ce17f892cd RV battery model and WiFi energy example diff -r bc947fbfac80 -r d8909a1fd0ff CHANGES.html --- a/CHANGES.html Mon Dec 20 15:19:11 2010 -0800 +++ b/CHANGES.html Mon Dec 20 15:49:12 2010 -0800 @@ -94,6 +94,10 @@ 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. +

+ +
  • Rakhmatov Vrudhula non-linear battery model +

    New class and helper for this battery model.

  • diff -r bc947fbfac80 -r d8909a1fd0ff RELEASE_NOTES --- a/RELEASE_NOTES Mon Dec 20 15:19:11 2010 -0800 +++ b/RELEASE_NOTES Mon Dec 20 15:49:12 2010 -0800 @@ -71,6 +71,12 @@ 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 diff -r bc947fbfac80 -r d8909a1fd0ff examples/energy/energy-model-example.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/energy/energy-model-example.cc Mon Dec 20 15:49:12 2010 -0800 @@ -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 , He Wu + */ + +#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 +#include +#include +#include + +NS_LOG_COMPONENT_DEFINE ("EnergyExample"); + +using namespace ns3; + +/** + * \param socket Pointer to socket. + * + * Packet receiving sink. + */ +void +ReceivePacket (Ptr socket) +{ + Ptr 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, uint32_t pktSize, Ptr n, + uint32_t pktCount, Time pktInterval) +{ + if (pktCount > 0) + { + socket->Send (Create (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 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 positionAlloc = CreateObject (); + 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 recvSink = Socket::CreateSocket (networkNodes.Get (1), tid); // node 1, receiver + InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80); + recvSink->Bind (local); + recvSink->SetRecvCallback (MakeCallback (&ReceivePacket)); + + Ptr 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 basicSourcePtr = DynamicCast (sources.Get (1)); + basicSourcePtr->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback (&RemainingEnergy)); + // device energy model + Ptr 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; +} diff -r bc947fbfac80 -r d8909a1fd0ff examples/energy/waf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/energy/waf Mon Dec 20 15:49:12 2010 -0800 @@ -0,0 +1,1 @@ +exec "`dirname "$0"`"/../../waf "$@" diff -r bc947fbfac80 -r d8909a1fd0ff examples/energy/wscript --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/energy/wscript Mon Dec 20 15:49:12 2010 -0800 @@ -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' \ No newline at end of file diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/helper/energy-model-helper.cc --- a/src/contrib/energy/helper/energy-model-helper.cc Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/helper/energy-model-helper.cc Mon Dec 20 15:49:12 2010 -0800 @@ -93,6 +93,7 @@ { 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 @@ 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 model = DoInstall (*dev, *src); container.Add (model); diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/helper/energy-source-container.cc --- a/src/contrib/energy/helper/energy-source-container.cc Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/helper/energy-source-container.cc Mon Dec 20 15:49:12 2010 -0800 @@ -118,6 +118,13 @@ void EnergySourceContainer::DoDispose (void) { + // call Object::Dispose for all EnergySource objects + for (std::vector< Ptr >::iterator i = m_sources.begin (); + i != m_sources.end (); i++) + { + (*i)->DisposeDeviceModels (); + (*i)->Dispose (); + } m_sources.clear (); } @@ -126,9 +133,10 @@ { // call Object::Start for all EnergySource objects for (std::vector< Ptr >::iterator i = m_sources.begin (); - i != m_sources.end (); i++) + i != m_sources.end (); i++) { (*i)->Start (); + (*i)->StartDeviceModels (); } } diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/helper/rv-battery-model-helper.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/energy/helper/rv-battery-model-helper.cc Mon Dec 20 15:49:12 2010 -0800 @@ -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 , He Wu + */ + +#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 +RvBatteryModelHelper::DoInstall (Ptr node) const +{ + NS_ASSERT (node != NULL); + // check if energy source already exists + Ptr source = node->GetObject (); + if (source != NULL) + { + NS_FATAL_ERROR ("Energy source already installed!"); + } + source = m_rvBatteryModel.Create (); + NS_ASSERT (source != NULL); + source->SetNode (node); + return source; +} + +} // namespace ns3 diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/helper/rv-battery-model-helper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/energy/helper/rv-battery-model-helper.h Mon Dec 20 15:49:12 2010 -0800 @@ -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 , He Wu + */ + +#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 DoInstall (Ptr node) const; + +private: + ObjectFactory m_rvBatteryModel; + +}; + +} // namespace ns3 + +#endif /* RV_BATTERY_MODEL_HELPER_H */ diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/helper/wifi-radio-energy-model-helper.cc --- a/src/contrib/energy/helper/wifi-radio-energy-model-helper.cc Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/helper/wifi-radio-energy-model-helper.cc Mon Dec 20 15:49:12 2010 -0800 @@ -67,23 +67,18 @@ NS_FATAL_ERROR ("NetDevice type is not WifiNetDevice!"); } Ptr node = device->GetNode (); - Ptr model = m_radioEnergy.Create ()-> - GetObject (); + Ptr model = m_radioEnergy.Create ()->GetObject (); 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 wifiDevice = DynamicCast (device); Ptr wifiPhy = wifiDevice->GetPhy (); - DeviceEnergyModel::ChangeStateCallback callback; - callback = MakeCallback (&DeviceEnergyModel::ChangeState, model); - //wifiPhy->SetEnergyModelCallback (callback); + wifiPhy->RegisterListener (model->GetPhyListener ()); return model; } diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/basic-energy-source.cc --- a/src/contrib/energy/model/basic-energy-source.cc Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/model/basic-energy-source.cc Mon Dec 20 15:49:12 2010 -0800 @@ -90,28 +90,25 @@ 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; } @@ -134,32 +131,10 @@ } 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 @@ 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 } diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/basic-energy-source.h --- a/src/contrib/energy/model/basic-energy-source.h Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/model/basic-energy-source.h Mon Dec 20 15:49:12 2010 -0800 @@ -68,20 +68,6 @@ 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. */ virtual void UpdateEnergySource (void); @@ -116,7 +102,10 @@ private: + /// Defined in ns3::Object void DoStart (void); + + /// Defined in ns3::Object void DoDispose (void); /** diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/device-energy-model.h --- a/src/contrib/energy/model/device-energy-model.h Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/model/device-energy-model.h Mon Dec 20 15:49:12 2010 -0800 @@ -53,20 +53,6 @@ virtual ~DeviceEnergyModel (); /** - * \brief Sets pointer to node containing this EnergySource. - * - * \param node Pointer to node containing this EnergySource. - */ - virtual void SetNode (Ptr node) = 0; - - /** - * \brief Gets pointer to node containing this EnergySource. - * - * \returns Pointer to node containing this EnergySource. - */ - virtual Ptr GetNode (void) const = 0; - - /** * \param source Pointer to energy source installed on node. * * This function sets the pointer to energy source installed on node. Should diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/energy-source.cc --- a/src/contrib/energy/model/energy-source.cc Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/model/energy-source.cc Mon Dec 20 15:49:12 2010 -0800 @@ -47,7 +47,6 @@ void EnergySource::SetNode (Ptr node) { - NS_LOG_FUNCTION (this << node); NS_ASSERT (node != NULL); m_node = node; } @@ -55,7 +54,6 @@ Ptr EnergySource::GetNode (void) const { - NS_LOG_FUNCTION (this); return m_node; } @@ -99,6 +97,34 @@ 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 @@ EnergySource::DoDispose (void) { NS_LOG_FUNCTION (this); - m_models.Clear (); + BreakDeviceEnergyModelRefCycle (); } /* diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/energy-source.h --- a/src/contrib/energy/model/energy-source.h Mon Dec 20 15:19:11 2010 -0800 +++ b/src/contrib/energy/model/energy-source.h Mon Dec 20 15:49:12 2010 -0800 @@ -97,22 +97,6 @@ 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 * DeviceEnergyModels to inform EnergySource of a state change. @@ -154,11 +138,27 @@ */ 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 @@ 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 m_node; diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/rv-battery-model.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/energy/model/rv-battery-model.cc Mon Dec 20 15:49:12 2010 -0800 @@ -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 , He Wu + */ + +#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 + +NS_LOG_COMPONENT_DEFINE ("RvBatteryModel"); + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (RvBatteryModel); + +TypeId +RvBatteryModel::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RvBatteryModel") + .SetParent () + .AddConstructor () + .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 ()) + .AddAttribute ("RvBatteryModelCutoffVoltage", + "RV battery model cutoff voltage.", + DoubleValue (3.0), + MakeDoubleAccessor (&RvBatteryModel::SetCutoffVoltage, + &RvBatteryModel::GetCutoffVoltage), + MakeDoubleChecker ()) + .AddAttribute ("RvBatteryModelAlphaValue", + "RV battery model alpha value.", + DoubleValue (35220.0), + MakeDoubleAccessor (&RvBatteryModel::SetAlpha, + &RvBatteryModel::GetAlpha), + MakeDoubleChecker ()) + .AddAttribute ("RvBatteryModelBetaValue", + "RV battery model beta value.", + DoubleValue (0.637), + MakeDoubleAccessor (&RvBatteryModel::SetBeta, + &RvBatteryModel::GetBeta), + MakeDoubleChecker ()) + .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 ()) + .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 diff -r bc947fbfac80 -r d8909a1fd0ff src/contrib/energy/model/rv-battery-model.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/contrib/energy/model/rv-battery-model.h Mon Dec 20 15:49:12 2010 -0800 @@ -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 , He Wu + */ + +#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 m_load; // load profile + std::vector