src/contrib/energy/test/rv-battery-model-test.cc
changeset 6938 85d201f1c67f
parent 6937 99ee62eec34c
child 6939 9fe35f79fd8f
equal deleted inserted replaced
6937:99ee62eec34c 6938:85d201f1c67f
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2010 Network Security Lab, University of Washington, Seattle.
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  * Author: He Wu <mdzz@u.washington.edu>
       
    19  */
       
    20 
       
    21 #include "ns3/rv-battery-model.h"
       
    22 #include "ns3/wifi-radio-energy-model.h"
       
    23 #include "ns3/rv-battery-model-helper.h"
       
    24 #include "ns3/wifi-radio-energy-model-helper.h"
       
    25 #include "ns3/energy-source-container.h"
       
    26 #include "ns3/device-energy-model-container.h"
       
    27 #include "ns3/log.h"
       
    28 #include "ns3/test.h"
       
    29 #include "ns3/node.h"
       
    30 #include "ns3/simulator.h"
       
    31 #include "ns3/double.h"
       
    32 #include "ns3/config.h"
       
    33 #include "ns3/string.h"
       
    34 #include "ns3/yans-wifi-helper.h"
       
    35 #include "ns3/nqos-wifi-mac-helper.h"
       
    36 #include <math.h>
       
    37 
       
    38 using namespace ns3;
       
    39 
       
    40 NS_LOG_COMPONENT_DEFINE ("RvBatteryModelTestSuite");
       
    41 
       
    42 /**
       
    43  * Test case of update remaining energy for RvBatteryModel and
       
    44  * WifiRadioEnergyModel.
       
    45  */
       
    46 class BatteryLifetimeTest : public TestCase
       
    47 {
       
    48 public:
       
    49   BatteryLifetimeTest ();
       
    50   virtual ~BatteryLifetimeTest ();
       
    51 
       
    52 private:
       
    53   /**
       
    54    * Creates load profiles according to "Battery Lifetime Prediction for Energy-
       
    55    * Aware Computing" paper.
       
    56    */
       
    57   void CreateLoadProfiles (void);
       
    58 
       
    59   /**
       
    60    * \returns False if no error occurs.
       
    61    *
       
    62    * Runs test.
       
    63    */
       
    64   void DoRun (void);
       
    65 
       
    66   /**
       
    67    * \param load Load value, in Amperes (A).
       
    68    * \param expLifetime Expected lifetime.
       
    69    * \return False if no error occurs.
       
    70    *
       
    71    * Runs simulation with constant load and checks the battery lifetime with
       
    72    * known results.
       
    73    */
       
    74   bool ConstantLoadTest (double load, Time expLifetime);
       
    75 
       
    76   /**
       
    77    * \param loads Load profile.
       
    78    * \param timeStamps Time stamps.
       
    79    * \param expLifeTime Expected lifetime.
       
    80    * \returns False if no error occurs.
       
    81    *
       
    82    * Runs simulation with variable load and checks the battery lifetime with
       
    83    * known results.
       
    84    */
       
    85   bool VariableLoadTest (std::vector<double> loads,
       
    86                          std::vector<Time> timeStamps,
       
    87                          Time expLifetime);
       
    88 
       
    89 private:
       
    90   typedef struct LoadProfile
       
    91   {
       
    92     std::vector<double> loads;
       
    93     std::vector<Time> timeStamps;
       
    94     Time itsyLifetime;
       
    95     Time dualFoilLifeTime;
       
    96   } LoadProfile;
       
    97 
       
    98 private:
       
    99   std::vector<LoadProfile> m_loadProfiles;
       
   100   double m_alpha;
       
   101   double m_beta;
       
   102 };
       
   103 
       
   104 BatteryLifetimeTest::BatteryLifetimeTest ()
       
   105   : TestCase ("RV battery model battery lifetime test case.")
       
   106 {
       
   107   // Itsy battery
       
   108   m_alpha = 35220;
       
   109   m_beta = 0.637;
       
   110 }
       
   111 
       
   112 BatteryLifetimeTest::~BatteryLifetimeTest ()
       
   113 {
       
   114 }
       
   115 
       
   116 void
       
   117 BatteryLifetimeTest::CreateLoadProfiles (void)
       
   118 {
       
   119   // create set of load profiles
       
   120   LoadProfile profile;
       
   121 
       
   122   std::vector<double> loads;
       
   123   std::vector<Time> timeStamps;
       
   124 
       
   125   // C1
       
   126   loads.push_back (0.628);
       
   127   loads.push_back (0);
       
   128   loads.push_back (0.628);
       
   129 
       
   130   timeStamps.push_back (Seconds (0));
       
   131   timeStamps.push_back (Seconds (19.5 * 60));
       
   132   timeStamps.push_back (Seconds (26.0 * 60));
       
   133 
       
   134   profile.loads = loads;
       
   135   profile.timeStamps = timeStamps;
       
   136   profile.itsyLifetime = Seconds (55.0 * 60);     // 55.0 minutes
       
   137   profile.dualFoilLifeTime = Seconds (36.2 * 60); // 36.2 minutes
       
   138 
       
   139   m_loadProfiles.push_back (profile);
       
   140 
       
   141   loads.clear ();
       
   142   timeStamps.clear ();
       
   143 
       
   144   // C2
       
   145   loads.push_back (0.4947);
       
   146   loads.push_back (0);
       
   147   loads.push_back (0.4947);
       
   148 
       
   149   timeStamps.push_back (Seconds (0));
       
   150   timeStamps.push_back (Seconds (31.0 * 60));
       
   151   timeStamps.push_back (Seconds (41.3 * 60));
       
   152 
       
   153   profile.loads = loads;
       
   154   profile.timeStamps = timeStamps;
       
   155   profile.itsyLifetime = Seconds (73.9 * 60);     // 73.9 minutes
       
   156   profile.dualFoilLifeTime = Seconds (55.8 * 60); // 55.8 minutes
       
   157 
       
   158   m_loadProfiles.push_back (profile);
       
   159 
       
   160   loads.clear ();
       
   161   timeStamps.clear ();
       
   162 
       
   163   // C3
       
   164   loads.push_back (0.4256);
       
   165   loads.push_back (0);
       
   166   loads.push_back (0.4256);
       
   167 
       
   168   timeStamps.push_back (Seconds (0));
       
   169   timeStamps.push_back (Seconds (41.0 * 60));
       
   170   timeStamps.push_back (Seconds (54.6 * 60));
       
   171 
       
   172   profile.loads = loads;
       
   173   profile.timeStamps = timeStamps;
       
   174   profile.itsyLifetime = Seconds (88.8 * 60);     // 88.8 minutes
       
   175   profile.dualFoilLifeTime = Seconds (71.8 * 60); // 71.8 minutes
       
   176 
       
   177   m_loadProfiles.push_back (profile);
       
   178 
       
   179   loads.clear ();
       
   180   timeStamps.clear ();
       
   181 
       
   182   // C4
       
   183   loads.push_back (0.2923);
       
   184   loads.push_back (0);
       
   185   loads.push_back (0.2923);
       
   186 
       
   187   timeStamps.push_back (Seconds (0));
       
   188   timeStamps.push_back (Seconds (74.6 * 60));
       
   189   timeStamps.push_back (Seconds (99.5 * 60));
       
   190 
       
   191   profile.loads = loads;
       
   192   profile.timeStamps = timeStamps;
       
   193   profile.itsyLifetime = Seconds (137.8 * 60);      // 137.8 minutes
       
   194   profile.dualFoilLifeTime = Seconds (124.9 * 60);  // 124.9 minutes
       
   195 
       
   196   m_loadProfiles.push_back (profile);
       
   197 
       
   198   loads.clear ();
       
   199   timeStamps.clear ();
       
   200 
       
   201   // C5
       
   202   loads.push_back (0.2227);
       
   203   loads.push_back (0);
       
   204   loads.push_back (0.2227);
       
   205 
       
   206   timeStamps.push_back (Seconds (0));
       
   207   timeStamps.push_back (Seconds (105.7 * 60));
       
   208   timeStamps.push_back (Seconds (140.9 * 60));
       
   209 
       
   210   profile.loads = loads;
       
   211   profile.timeStamps = timeStamps;
       
   212   profile.itsyLifetime = Seconds (185.8 * 60);      // 185.8 minutes
       
   213   profile.dualFoilLifeTime = Seconds (176.7 * 60);  // 176.7 minutes
       
   214 
       
   215   m_loadProfiles.push_back (profile);
       
   216 
       
   217   loads.clear ();
       
   218   timeStamps.clear ();
       
   219 
       
   220   // C6
       
   221   loads.push_back (0.628);
       
   222   loads.push_back (0);
       
   223   loads.push_back (0.628);
       
   224 
       
   225   timeStamps.push_back (Seconds (0));
       
   226   timeStamps.push_back (Seconds (19.5 * 60));
       
   227   timeStamps.push_back (Seconds (29.9 * 60));
       
   228 
       
   229   profile.loads = loads;
       
   230   profile.timeStamps = timeStamps;
       
   231   profile.itsyLifetime = Seconds (58.9 * 60);     // 58.9 minutes
       
   232   profile.dualFoilLifeTime = Seconds (41.0 * 60); // 41.0 minutes
       
   233 
       
   234   m_loadProfiles.push_back (profile);
       
   235 
       
   236   loads.clear ();
       
   237   timeStamps.clear ();
       
   238 
       
   239   // C7
       
   240   loads.push_back (0.628);
       
   241   loads.push_back (0);
       
   242   loads.push_back (0.628);
       
   243 
       
   244   timeStamps.push_back (Seconds (0));
       
   245   timeStamps.push_back (Seconds (19.5 * 60));
       
   246   timeStamps.push_back (Seconds (22.1 * 60));
       
   247 
       
   248   profile.loads = loads;
       
   249   profile.timeStamps = timeStamps;
       
   250   profile.itsyLifetime = Seconds (51.1 * 60);     // 51.1 minutes
       
   251   profile.dualFoilLifeTime = Seconds (30.8 * 60); // 30.8 minutes
       
   252 
       
   253   m_loadProfiles.push_back (profile);
       
   254 
       
   255   loads.clear ();
       
   256   timeStamps.clear ();
       
   257 
       
   258   // C8
       
   259   loads.push_back (0.628);
       
   260   loads.push_back (0);
       
   261   loads.push_back (0.628);
       
   262 
       
   263   timeStamps.push_back (Seconds (0));
       
   264   timeStamps.push_back (Seconds (23.4 * 60));
       
   265   timeStamps.push_back (Seconds (29.9 * 60));
       
   266 
       
   267   profile.loads = loads;
       
   268   profile.timeStamps = timeStamps;
       
   269   profile.itsyLifetime = Seconds (55.0 * 60);     // 55.0 minutes
       
   270   profile.dualFoilLifeTime = Seconds (37.4 * 60); // 37.4 minutes
       
   271 
       
   272   m_loadProfiles.push_back (profile);
       
   273 
       
   274   loads.clear ();
       
   275   timeStamps.clear ();
       
   276 
       
   277   // C9
       
   278   loads.push_back (0.628);
       
   279   loads.push_back (0);
       
   280   loads.push_back (0.628);
       
   281 
       
   282   timeStamps.push_back (Seconds (0));
       
   283   timeStamps.push_back (Seconds (15.6 * 60));
       
   284   timeStamps.push_back (Seconds (22.1 * 60));
       
   285 
       
   286   profile.loads = loads;
       
   287   profile.timeStamps = timeStamps;
       
   288   profile.itsyLifetime = Seconds (55.0 * 60);     // 55.0 minutes
       
   289   profile.dualFoilLifeTime = Seconds (35.2 * 60); // 35.2 minutes
       
   290 
       
   291   m_loadProfiles.push_back (profile);
       
   292 
       
   293   loads.clear ();
       
   294   timeStamps.clear ();
       
   295 
       
   296   // C10
       
   297   loads.push_back (0.300);
       
   298   loads.push_back (0.628);
       
   299   loads.push_back (0.4947);
       
   300   loads.push_back (0.2523);
       
   301   loads.push_back (0.2341);
       
   302   loads.push_back (0.1379);
       
   303   loads.push_back (0.1139);
       
   304   loads.push_back (0.2656);
       
   305 
       
   306   timeStamps.push_back (Seconds (0));
       
   307   timeStamps.push_back (Seconds (0.5 * 60));
       
   308   timeStamps.push_back (Seconds (5.5 * 60));
       
   309   timeStamps.push_back (Seconds (10.5 * 60));
       
   310   timeStamps.push_back (Seconds (35.5 * 60));
       
   311   timeStamps.push_back (Seconds (60.5 * 60));
       
   312   timeStamps.push_back (Seconds (85.5 * 60));
       
   313   timeStamps.push_back (Seconds (110.5 * 60));
       
   314 
       
   315   profile.loads = loads;
       
   316   profile.timeStamps = timeStamps;
       
   317   profile.itsyLifetime = Seconds (144.3 * 60);      // 144.3 minutes
       
   318   profile.dualFoilLifeTime = Seconds (132.6 * 60);  // 132.6 minutes
       
   319 
       
   320   m_loadProfiles.push_back (profile);
       
   321 
       
   322   loads.clear ();
       
   323   timeStamps.clear ();
       
   324 
       
   325   // C11
       
   326   loads.push_back (0.300);
       
   327   loads.push_back (0.1139);
       
   328   loads.push_back (0.1379);
       
   329   loads.push_back (0.2341);
       
   330   loads.push_back (0.2523);
       
   331   loads.push_back (0.4947);
       
   332   loads.push_back (0.628);
       
   333   loads.push_back (0.2656);
       
   334 
       
   335   timeStamps.push_back (Seconds (0));
       
   336   timeStamps.push_back (Seconds (0.5 * 60));
       
   337   timeStamps.push_back (Seconds (25.5 * 60));
       
   338   timeStamps.push_back (Seconds (50.5 * 60));
       
   339   timeStamps.push_back (Seconds (75.5 * 60));
       
   340   timeStamps.push_back (Seconds (100.5 * 60));
       
   341   timeStamps.push_back (Seconds (105.5 * 60));
       
   342   timeStamps.push_back (Seconds (110.5 * 60));
       
   343 
       
   344   profile.loads = loads;
       
   345   profile.timeStamps = timeStamps;
       
   346   profile.itsyLifetime = Seconds (144.3 * 60);      // 144.3 minutes
       
   347   profile.dualFoilLifeTime = Seconds (107.4 * 60);  // 107.4 minutes
       
   348 
       
   349   m_loadProfiles.push_back (profile);
       
   350 
       
   351   loads.clear ();
       
   352   timeStamps.clear ();
       
   353 
       
   354   // C12
       
   355   loads.push_back (0.300);
       
   356   loads.push_back (0.1139);
       
   357   loads.push_back (0.1379);
       
   358   loads.push_back (0.2341);
       
   359   loads.push_back (0.2523);
       
   360   loads.push_back (0.4947);
       
   361   loads.push_back (0.0);
       
   362   loads.push_back (0.300);
       
   363   loads.push_back (0.628);
       
   364   loads.push_back (0.2656);
       
   365 
       
   366   timeStamps.push_back (Seconds (0));
       
   367   timeStamps.push_back (Seconds (0.5 * 60));
       
   368   timeStamps.push_back (Seconds (25.5 * 60));
       
   369   timeStamps.push_back (Seconds (50.5 * 60));
       
   370   timeStamps.push_back (Seconds (75.5 * 60));
       
   371   timeStamps.push_back (Seconds (100.5 * 60));
       
   372   timeStamps.push_back (Seconds (105.5 * 60));
       
   373   timeStamps.push_back (Seconds (130.5 * 60));
       
   374   timeStamps.push_back (Seconds (131.0 * 60));
       
   375   timeStamps.push_back (Seconds (136.0 * 60));
       
   376 
       
   377   profile.loads = loads;
       
   378   profile.timeStamps = timeStamps;
       
   379   profile.itsyLifetime = Seconds (169.3 * 60);      // 169.3 minutes
       
   380   profile.dualFoilLifeTime = Seconds (155.4 * 60);  // 155.4 minutes
       
   381 
       
   382   m_loadProfiles.push_back (profile);
       
   383 
       
   384   loads.clear ();
       
   385   timeStamps.clear ();
       
   386 
       
   387   // C13
       
   388   loads.push_back (0.300);
       
   389   timeStamps.push_back (Seconds (0));
       
   390 
       
   391   for (int i = 0; i < 5; i++)
       
   392     {
       
   393       loads.push_back (0.628);
       
   394       loads.push_back (0.4947);
       
   395       loads.push_back (0.2523);
       
   396       loads.push_back (0.2341);
       
   397       loads.push_back (0.1379);
       
   398       loads.push_back (0.1139);
       
   399 
       
   400       timeStamps.push_back (Seconds ((0.5 + i * 22.5) * 60));
       
   401       timeStamps.push_back (Seconds ((1.5 + i * 22.5) * 60));
       
   402       timeStamps.push_back (Seconds ((2.5 + i * 22.5) * 60));
       
   403       timeStamps.push_back (Seconds ((7.5 + i * 22.5) * 60));
       
   404       timeStamps.push_back (Seconds ((12.5 + i * 22.5) * 60));
       
   405       timeStamps.push_back (Seconds ((17.5 + i * 22.5) * 60));
       
   406     }
       
   407 
       
   408   loads.push_back (0.2656);
       
   409   timeStamps.push_back (Seconds (110.5 * 60));
       
   410 
       
   411   profile.loads = loads;
       
   412   profile.timeStamps = timeStamps;
       
   413   profile.itsyLifetime = Seconds (144.3 * 60);      // 144.3 minutes
       
   414   profile.dualFoilLifeTime = Seconds (131.7 * 60);  // 131.7 minutes
       
   415 
       
   416   m_loadProfiles.push_back (profile);
       
   417 
       
   418   loads.clear ();
       
   419   timeStamps.clear ();
       
   420 
       
   421   // C14, time stamp calculation in paper is off, using our own estimated value
       
   422   loads.push_back (0.300);
       
   423   timeStamps.push_back (Seconds (0));
       
   424 
       
   425   for (int i = 0; i < 5; i++)
       
   426     {
       
   427       loads.push_back (0.1139);
       
   428       loads.push_back (0.1379);
       
   429       loads.push_back (0.2341);
       
   430       loads.push_back (0.2523);
       
   431       loads.push_back (0.4947);
       
   432       loads.push_back (0.628);
       
   433 
       
   434       timeStamps.push_back (Seconds ((0.5 + i * 22.5) * 60));
       
   435       timeStamps.push_back (Seconds ((5.5 + i * 22.5) * 60));
       
   436       timeStamps.push_back (Seconds ((10.5 + i * 22.5) * 60));
       
   437       timeStamps.push_back (Seconds ((15.5 + i * 22.5) * 60));
       
   438       timeStamps.push_back (Seconds ((20.5 + i * 22.5) * 60));
       
   439       timeStamps.push_back (Seconds ((21.5 + i * 22.5) * 60));
       
   440     }
       
   441 
       
   442   loads.push_back (0.2656);
       
   443   timeStamps.push_back (Seconds (112.5 * 60));
       
   444 
       
   445   profile.loads = loads;
       
   446   profile.timeStamps = timeStamps;
       
   447   profile.itsyLifetime = Seconds (141.5 * 60);      // 141.5 minutes
       
   448   profile.dualFoilLifeTime = Seconds (126.3 * 60);  // 126.3 minutes
       
   449 
       
   450   m_loadProfiles.push_back (profile);
       
   451 
       
   452   loads.clear ();
       
   453   timeStamps.clear ();
       
   454 
       
   455   // C15
       
   456   loads.push_back (0.2227);
       
   457   loads.push_back (0.2045);
       
   458   loads.push_back (0.1083);
       
   459   loads.push_back (0.0843);
       
   460   loads.push_back (0.2227);
       
   461 
       
   462   timeStamps.push_back (Seconds (0));
       
   463   timeStamps.push_back (Seconds (50.0 * 60));
       
   464   timeStamps.push_back (Seconds (100.0 * 60));
       
   465   timeStamps.push_back (Seconds (150.0 * 60));
       
   466   timeStamps.push_back (Seconds (200.0 * 60));
       
   467 
       
   468   profile.loads = loads;
       
   469   profile.timeStamps = timeStamps;
       
   470   profile.itsyLifetime = Seconds (211.4 * 60);      // 211.4 minutes
       
   471   profile.dualFoilLifeTime = Seconds (209.2 * 60);  // 209.2 minutes
       
   472 
       
   473   m_loadProfiles.push_back (profile);
       
   474 
       
   475   loads.clear ();
       
   476   timeStamps.clear ();
       
   477 
       
   478   // C16
       
   479   loads.push_back (0.0843);
       
   480   loads.push_back (0.1083);
       
   481   loads.push_back (0.2045);
       
   482   loads.push_back (0.2227);
       
   483   loads.push_back (0.2227);
       
   484 
       
   485   timeStamps.push_back (Seconds (0));
       
   486   timeStamps.push_back (Seconds (50.0 * 60));
       
   487   timeStamps.push_back (Seconds (100.0 * 60));
       
   488   timeStamps.push_back (Seconds (150.0 * 60));
       
   489   timeStamps.push_back (Seconds (200.0 * 60));
       
   490 
       
   491   profile.loads = loads;
       
   492   profile.timeStamps = timeStamps;
       
   493   profile.itsyLifetime = Seconds (211.4 * 60);      // 211.4 minutes
       
   494   profile.dualFoilLifeTime = Seconds (200.7 * 60);  // 200.7 minutes
       
   495 
       
   496   m_loadProfiles.push_back (profile);
       
   497 
       
   498   loads.clear ();
       
   499   timeStamps.clear ();
       
   500 
       
   501   // C17
       
   502   loads.push_back (0.0843);
       
   503   loads.push_back (0.1083);
       
   504   loads.push_back (0.2045);
       
   505   loads.push_back (0.0);
       
   506   loads.push_back (0.2227);
       
   507   loads.push_back (0.2227);
       
   508 
       
   509   timeStamps.push_back (Seconds (0));
       
   510   timeStamps.push_back (Seconds (50.0 * 60));
       
   511   timeStamps.push_back (Seconds (100.0 * 60));
       
   512   timeStamps.push_back (Seconds (150.0 * 60));
       
   513   timeStamps.push_back (Seconds (200.0 * 60));
       
   514   timeStamps.push_back (Seconds (250.0 * 60));
       
   515 
       
   516   profile.loads = loads;
       
   517   profile.timeStamps = timeStamps;
       
   518   profile.itsyLifetime = Seconds (261.4 * 60);      // 261.4 minutes
       
   519   profile.dualFoilLifeTime = Seconds (251.2 * 60);  // 251.2 minutes
       
   520 
       
   521   m_loadProfiles.push_back (profile);
       
   522 
       
   523   loads.clear ();
       
   524   timeStamps.clear ();
       
   525 
       
   526   // C18
       
   527   for (int i = 0; i < 10; i++)
       
   528     {
       
   529       loads.push_back (0.0843);
       
   530       loads.push_back (0.1083);
       
   531       loads.push_back (0.2045);
       
   532       loads.push_back (0.2227);
       
   533 
       
   534       timeStamps.push_back (Seconds ((0.0 + i * 20.0) * 60));
       
   535       timeStamps.push_back (Seconds ((5.0 + i * 20.0) * 60));
       
   536       timeStamps.push_back (Seconds ((10.0 + i * 20.0) * 60));
       
   537       timeStamps.push_back (Seconds ((15.0 + i * 20.0) * 60));
       
   538     }
       
   539 
       
   540   loads.push_back (0.2227);
       
   541   timeStamps.push_back (Seconds (200.0));
       
   542 
       
   543   profile.loads = loads;
       
   544   profile.timeStamps = timeStamps;
       
   545   profile.itsyLifetime = Seconds (211.4 * 60);      // 211.4 minutes
       
   546   profile.dualFoilLifeTime = Seconds (204.6 * 60);  // 204.6 minutes
       
   547 
       
   548   m_loadProfiles.push_back (profile);
       
   549 
       
   550   loads.clear ();
       
   551   timeStamps.clear ();
       
   552 
       
   553   // C19
       
   554   for (int i = 0; i < 10; i++)
       
   555     {
       
   556       loads.push_back (0.0755);
       
   557       loads.push_back (0.0949);
       
   558       loads.push_back (0.2045);
       
   559       loads.push_back (0.2227);
       
   560 
       
   561       timeStamps.push_back (Seconds ((0.0 + i * 20.0) * 60));
       
   562       timeStamps.push_back (Seconds ((5.0 + i * 20.0) * 60));
       
   563       timeStamps.push_back (Seconds ((10.0 + i * 20.0) * 60));
       
   564       timeStamps.push_back (Seconds ((15.0 + i * 20.0) * 60));
       
   565     }
       
   566 
       
   567   loads.push_back (0.2227);
       
   568   timeStamps.push_back (Seconds (200.0));
       
   569 
       
   570   profile.loads = loads;
       
   571   profile.timeStamps = timeStamps;
       
   572   profile.itsyLifetime = Seconds (216.4 * 60);      // 216.4 minutes
       
   573   profile.dualFoilLifeTime = Seconds (208.7 * 60);  // 208.7 minutes
       
   574 
       
   575   m_loadProfiles.push_back (profile);
       
   576 
       
   577   loads.clear ();
       
   578   timeStamps.clear ();
       
   579 
       
   580   // C20
       
   581   for (int i = 0; i < 50; i++)
       
   582     {
       
   583       loads.push_back (0.4947);
       
   584       loads.push_back (0.628);
       
   585 
       
   586       timeStamps.push_back (Seconds ((0.0 + i * 2.0) * 60));
       
   587       timeStamps.push_back (Seconds ((1.0 + i * 2.0) * 60));
       
   588     }
       
   589 
       
   590   profile.loads = loads;
       
   591   profile.timeStamps = timeStamps;
       
   592   profile.itsyLifetime = Seconds (55.3 * 60);       // 55.3 minutes
       
   593   profile.dualFoilLifeTime = Seconds (33.2 * 60);   // 33.2 minutes
       
   594 
       
   595   m_loadProfiles.push_back (profile);
       
   596 
       
   597   loads.clear ();
       
   598   timeStamps.clear ();
       
   599 
       
   600   // C21
       
   601   for (int i = 0; i < 50; i++)
       
   602     {
       
   603       loads.push_back (0.4947);
       
   604       loads.push_back (0.628);
       
   605       loads.push_back (0.0576);
       
   606 
       
   607       timeStamps.push_back (Seconds ((0.0 + i * 3.0) * 60));
       
   608       timeStamps.push_back (Seconds ((1.0 + i * 3.0) * 60));
       
   609       timeStamps.push_back (Seconds ((2.0 + i * 3.0) * 60));
       
   610     }
       
   611 
       
   612   profile.loads = loads;
       
   613   profile.timeStamps = timeStamps;
       
   614   profile.itsyLifetime = Seconds (79.6 * 60);       // 79.6 minutes
       
   615   profile.dualFoilLifeTime = Seconds (55.9 * 60);   // 55.9 minutes
       
   616 
       
   617   m_loadProfiles.push_back (profile);
       
   618 
       
   619   loads.clear ();
       
   620   timeStamps.clear ();
       
   621 
       
   622   // C22
       
   623   for (int i = 0; i < 150; i++)
       
   624     {
       
   625       loads.push_back (0.005 + 0.005 * i);
       
   626       timeStamps.push_back (Seconds ((0.0 + i * 1.0) * 60));
       
   627     }
       
   628 
       
   629   profile.loads = loads;
       
   630   profile.timeStamps = timeStamps;
       
   631   profile.itsyLifetime = Seconds (112.2 * 60);      // 112.2 minutes
       
   632   profile.dualFoilLifeTime = Seconds (94.5 * 60);   // 94.5 minutes
       
   633 
       
   634   m_loadProfiles.push_back (profile);
       
   635 
       
   636   loads.clear ();
       
   637   timeStamps.clear ();
       
   638 }
       
   639 
       
   640 void
       
   641 BatteryLifetimeTest::DoRun (void)
       
   642 {
       
   643   NS_LOG_UNCOND ("Constant load run.");
       
   644 
       
   645   // 640mA
       
   646   NS_TEST_ASSERT_MSG_EQ (ConstantLoadTest (0.640, Seconds (2844.0)), false,  "Problems with constant load test (640mA).");
       
   647   // 320mA
       
   648   NS_TEST_ASSERT_MSG_EQ (ConstantLoadTest (0.320, Seconds (6146.0)), false,  "Problems with constant load test (320mA).");
       
   649   // 128mA
       
   650   NS_TEST_ASSERT_MSG_EQ (ConstantLoadTest (0.128, Seconds (16052.0)), false,  "Problems with constant load test (128mA).");
       
   651   // 64mA
       
   652   NS_TEST_ASSERT_MSG_EQ (ConstantLoadTest (0.064, Seconds (32561.0)), false,  "Problems with constant load test (64mA).");
       
   653   // 32mA
       
   654   NS_TEST_ASSERT_MSG_EQ (ConstantLoadTest (0.032, Seconds (65580.0)), false,  "Problems with constant load test (32).");
       
   655 
       
   656   // create load profiles for variable load test
       
   657   CreateLoadProfiles ();
       
   658 
       
   659   // variable load with Itsy battery
       
   660   NS_LOG_UNCOND ("\n\nItsy");
       
   661   m_alpha = 35220;
       
   662   m_beta = 0.637;
       
   663   for (uint32_t i = 0; i < m_loadProfiles.size (); i++)
       
   664     {
       
   665       NS_LOG_UNCOND ("========");
       
   666       NS_LOG_UNCOND ("Variable load profile C" << i + 1);
       
   667       if (VariableLoadTest (m_loadProfiles[i].loads,
       
   668                             m_loadProfiles[i].timeStamps,
       
   669                             m_loadProfiles[i].itsyLifetime))
       
   670         {
       
   671           return;
       
   672         }
       
   673     }
       
   674 
       
   675   // variable load with DUALFOIL battery
       
   676   NS_LOG_UNCOND ("\n\nDUALFOIL");
       
   677   m_alpha = 40027;
       
   678   m_beta = 0.276;
       
   679   for (uint32_t i = 0; i < m_loadProfiles.size (); i++)
       
   680     {
       
   681       NS_LOG_UNCOND ("========");
       
   682       NS_LOG_UNCOND ("Variable load profile C" << i + 1);
       
   683       if (VariableLoadTest (m_loadProfiles[i].loads,
       
   684                             m_loadProfiles[i].timeStamps,
       
   685                             m_loadProfiles[i].dualFoilLifeTime))
       
   686         {
       
   687           return;
       
   688         }
       
   689     }
       
   690 }
       
   691 
       
   692 bool
       
   693 BatteryLifetimeTest::ConstantLoadTest (double load, Time expLifetime)
       
   694 {
       
   695   // create single node
       
   696   NodeContainer c;
       
   697   c.Create (1);
       
   698 
       
   699   std::string phyMode ("DsssRate1Mbps");
       
   700 
       
   701   // disable fragmentation for frames below 2200 bytes
       
   702   Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
       
   703                       StringValue ("2200"));
       
   704   // turn off RTS/CTS for frames below 2200 bytes
       
   705   Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
       
   706                       StringValue ("2200"));
       
   707   // Fix non-unicast data rate to be the same as that of unicast
       
   708   Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
       
   709                       StringValue (phyMode));
       
   710 
       
   711   // install YansWifiPhy
       
   712   WifiHelper wifi;
       
   713   wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
       
   714 
       
   715   YansWifiPhyHelper wifiPhy =  YansWifiPhyHelper::Default ();
       
   716   /*
       
   717    * This is one parameter that matters when using FixedRssLossModel, set it to
       
   718    * zero; otherwise, gain will be added.
       
   719    */
       
   720   wifiPhy.Set ("RxGain", DoubleValue (0));
       
   721   // ns-3 supports RadioTap and Prism tracing extensions for 802.11b
       
   722   wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
       
   723 
       
   724   YansWifiChannelHelper wifiChannel ;
       
   725   wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
       
   726   wifiPhy.SetChannel (wifiChannel.Create ());
       
   727 
       
   728   // Add a non-QoS upper MAC, and disable rate control
       
   729   NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
       
   730   wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
       
   731                                 "DataMode", StringValue(phyMode),
       
   732                                 "ControlMode", StringValue(phyMode));
       
   733   // Set it to ad-hoc mode
       
   734   wifiMac.SetType ("ns3::AdhocWifiMac");
       
   735   NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
       
   736 
       
   737   // Create and install battery model and device models
       
   738   // RV battery model
       
   739   RvBatteryModelHelper rvModelHelper;
       
   740   // Set alpha & beta values
       
   741   rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
       
   742   rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
       
   743   // install source
       
   744   EnergySourceContainer sources = rvModelHelper.Install (c);
       
   745   // device energy model
       
   746   WifiRadioEnergyModelHelper radioEnergyHelper;
       
   747   // set VariableLoadTestIDLE current, which will be the constant load
       
   748   radioEnergyHelper.Set ("IdleCurrentA", DoubleValue (load));
       
   749   // install on node
       
   750   DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
       
   751 
       
   752   // run simulation
       
   753   Simulator::Stop (Seconds (70000.0));
       
   754   Simulator::Run ();
       
   755 
       
   756   Time actualLifetime;
       
   757   Ptr<RvBatteryModel> srcPtr = DynamicCast<RvBatteryModel> (sources.Get (0));
       
   758   actualLifetime = srcPtr->GetLifetime ();
       
   759 
       
   760   NS_LOG_UNCOND ("Expected lifetime = " << expLifetime.GetSeconds () << "s");
       
   761   NS_LOG_UNCOND ("Actual lifetime = " << actualLifetime.GetSeconds () << "s");
       
   762 
       
   763   NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (actualLifetime, expLifetime, "Incorrect lifetime!");
       
   764   /*
       
   765   NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL (actualLifetime.GetSeconds () / 60,
       
   766                                          expLifetime.GetSeconds () / 60, 0.1,
       
   767                                          "Incorrect lifetime!");
       
   768    */
       
   769 
       
   770   Simulator::Destroy ();
       
   771 
       
   772   return false; // error free
       
   773 }
       
   774 
       
   775 bool
       
   776 BatteryLifetimeTest::VariableLoadTest (std::vector<double> loads,
       
   777                                        std::vector<Time> timeStamps,
       
   778                                        Time expLifetime)
       
   779 {
       
   780   NS_ASSERT (loads.size () == timeStamps.size ());
       
   781 
       
   782   // create single node
       
   783     NodeContainer c;
       
   784     c.Create (1);
       
   785 
       
   786     std::string phyMode ("DsssRate1Mbps");
       
   787 
       
   788     // disable fragmentation for frames below 2200 bytes
       
   789     Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
       
   790                         StringValue ("2200"));
       
   791     // turn off RTS/CTS for frames below 2200 bytes
       
   792     Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
       
   793                         StringValue ("2200"));
       
   794     // Fix non-unicast data rate to be the same as that of unicast
       
   795     Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
       
   796                         StringValue (phyMode));
       
   797 
       
   798     // install YansWifiPhy
       
   799     WifiHelper wifi;
       
   800     wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
       
   801 
       
   802     YansWifiPhyHelper wifiPhy =  YansWifiPhyHelper::Default ();
       
   803     /*
       
   804      * This is one parameter that matters when using FixedRssLossModel, set it to
       
   805      * zero; otherwise, gain will be added.
       
   806      */
       
   807     wifiPhy.Set ("RxGain", DoubleValue (0));
       
   808     // ns-3 supports RadioTap and Prism tracing extensions for 802.11b
       
   809     wifiPhy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO);
       
   810 
       
   811     YansWifiChannelHelper wifiChannel ;
       
   812     wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
       
   813     wifiPhy.SetChannel (wifiChannel.Create ());
       
   814 
       
   815     // Add a non-QoS upper MAC, and disable rate control
       
   816     NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
       
   817     wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
       
   818                                   "DataMode", StringValue(phyMode),
       
   819                                   "ControlMode", StringValue(phyMode));
       
   820     // Set it to ad-hoc mode
       
   821     wifiMac.SetType ("ns3::AdhocWifiMac");
       
   822     NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c);
       
   823 
       
   824     // Create and install battery model and device models
       
   825     // RV battery model
       
   826     RvBatteryModelHelper rvModelHelper;
       
   827     // Set alpha & beta values
       
   828     rvModelHelper.Set ("RvBatteryModelAlphaValue", DoubleValue (m_alpha));
       
   829     rvModelHelper.Set ("RvBatteryModelBetaValue", DoubleValue (m_beta));
       
   830     // install source
       
   831     EnergySourceContainer sources = rvModelHelper.Install (c);
       
   832     // device energy model
       
   833     WifiRadioEnergyModelHelper radioEnergyHelper;
       
   834     // set VariableLoadTestIDLE current, which will be the constant load
       
   835     radioEnergyHelper.Set ("IdleCurrentA", DoubleValue (loads[0]));
       
   836     // install on node
       
   837     DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
       
   838 
       
   839 
       
   840     Ptr<WifiRadioEnergyModel> wifiDevicePtr = DynamicCast<WifiRadioEnergyModel> (deviceModels.Get (0));
       
   841     // schedule load change events
       
   842     for (uint32_t i = 1; i < loads.size (); i++)
       
   843       {
       
   844         Simulator::Schedule (timeStamps[i], &WifiRadioEnergyModel::SetIdleCurrentA,
       
   845                              wifiDevicePtr, loads[i]);
       
   846       }
       
   847 
       
   848     // run simulation
       
   849     Simulator::Stop (Seconds (70000.0));
       
   850     Simulator::Run ();
       
   851 
       
   852     Time actualLifetime;
       
   853     Ptr<RvBatteryModel> srcPtr = DynamicCast<RvBatteryModel> (sources.Get (0));
       
   854     actualLifetime = srcPtr->GetLifetime ();
       
   855 
       
   856     NS_LOG_UNCOND ("Expected lifetime = " << expLifetime.GetSeconds () << "s");
       
   857     NS_LOG_UNCOND ("Actual lifetime = " << actualLifetime.GetSeconds () << "s");
       
   858     NS_LOG_UNCOND ("Difference = " << expLifetime.GetSeconds () - actualLifetime.GetSeconds () << "s");
       
   859 
       
   860     //NS_TEST_ASSERT_MSG_EQ_RETURNS_BOOL (actualLifetime, expLifetime, "Incorrect lifetime!");
       
   861     NS_TEST_ASSERT_MSG_EQ_TOL_RETURNS_BOOL (actualLifetime.GetSeconds (), expLifetime.GetSeconds (),
       
   862                                120, // error tolerance = 120s
       
   863                                "Incorrect lifetime!");
       
   864 
       
   865     Simulator::Destroy ();
       
   866 
       
   867     return false; // error free
       
   868 }
       
   869 
       
   870 // -------------------------------------------------------------------------- //
       
   871 
       
   872 /**
       
   873  * Unit test suite for energy model. Although the test suite involves 2 modules
       
   874  * it is still considered a unit test. Because a DeviceEnergyModel cannot live
       
   875  * without an EnergySource.
       
   876  */
       
   877 class RvBatteryModelTestSuite : public TestSuite
       
   878 {
       
   879 public:
       
   880   RvBatteryModelTestSuite ();
       
   881 };
       
   882 
       
   883 RvBatteryModelTestSuite::RvBatteryModelTestSuite ()
       
   884   : TestSuite ("rv-battery-model", SYSTEM)
       
   885 {
       
   886   AddTestCase (new BatteryLifetimeTest);
       
   887 }
       
   888 
       
   889 // create an instance of the test suite
       
   890 static RvBatteryModelTestSuite g_rvBatteryModelTestSuite;