doxygen] Suppress "warning: Member NS_OBJECT_ENSURE_REGISTERED is not documented"
/* -*- 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 <cmath>
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 ()
{
NS_LOG_FUNCTION (this);
m_lastSampleTime = Seconds (0.0);
m_previousLoad = 0.0;
m_batteryLevel = 1; // fully charged
m_lifetime = Seconds (0.0);
}
RvBatteryModel::~RvBatteryModel ()
{
NS_LOG_FUNCTION (this);
}
double
RvBatteryModel::GetInitialEnergy (void) const
{
NS_LOG_FUNCTION (this);
return m_alpha * GetSupplyVoltage ();
}
double
RvBatteryModel::GetSupplyVoltage (void) const
{
NS_LOG_FUNCTION (this);
// 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)
{
NS_LOG_FUNCTION (this);
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
{
NS_LOG_FUNCTION (this);
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
{
NS_LOG_FUNCTION (this);
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
{
NS_LOG_FUNCTION (this);
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
{
NS_LOG_FUNCTION (this);
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
{
NS_LOG_FUNCTION (this);
return m_beta;
}
double
RvBatteryModel::GetBatteryLevel (void)
{
NS_LOG_FUNCTION (this);
UpdateEnergySource ();
return m_batteryLevel;
}
Time
RvBatteryModel::GetLifetime (void) const
{
NS_LOG_FUNCTION (this);
return m_lifetime;
}
void
RvBatteryModel::SetNumOfTerms (int num)
{
NS_LOG_FUNCTION (this << num);
m_numOfTerms = num;
}
int
RvBatteryModel::GetNumOfTerms (void) const
{
NS_LOG_FUNCTION (this);
return m_numOfTerms;
}
/*
* Private functions start here.
*/
void
RvBatteryModel::DoInitialize (void)
{
NS_LOG_FUNCTION (this);
NS_LOG_DEBUG ("RvBatteryModel:Starting battery level update!");
UpdateEnergySource (); // start periodic sampling of load (total current)
}
void
RvBatteryModel::DoDispose (void)
{
NS_LOG_FUNCTION (this);
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 += (std::exp (-square * (firstDelta)) - std::exp (-square * (secondDelta))) / square;
}
return delta + 2 * sum;
}
} // namespace ns3