Added uModem PER/SINR model
authorltracy
Wed Apr 01 16:00:30 2009 -0700 (10 months ago)
changeset 43088f024caae5d7
parent 4307 2bbc48af9aec
child 4309 3218cefc6dc6
Added uModem PER/SINR model
src/devices/uan/uan-phy-gen.cc
src/devices/uan/uan-phy-gen.h
src/devices/uan/uan-tx-mode.h
     1.1 --- a/src/devices/uan/uan-phy-gen.cc	Wed Apr 01 01:35:43 2009 -0700
     1.2 +++ b/src/devices/uan/uan-phy-gen.cc	Wed Apr 01 16:00:30 2009 -0700
     1.3 @@ -31,6 +31,7 @@
     1.4  #include "ns3/log.h"
     1.5  #include "ns3/uan-tx-mode.h"
     1.6  #include "ns3/node.h"
     1.7 +#include "ns3/uinteger.h"
     1.8  
     1.9  #include <iostream>
    1.10  NS_LOG_COMPONENT_DEFINE("UanPhyGen");
    1.11 @@ -41,6 +42,8 @@
    1.12  NS_OBJECT_ENSURE_REGISTERED (UanPhyGen);
    1.13  NS_OBJECT_ENSURE_REGISTERED (UanPhyPerGenDefault);
    1.14  NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrDefault);
    1.15 +NS_OBJECT_ENSURE_REGISTERED (UanPhyCalcSinrFhFsk);
    1.16 +NS_OBJECT_ENSURE_REGISTERED (UanPhyPerUmodem);
    1.17  
    1.18  UanPhyCalcSinrDefault::UanPhyCalcSinrDefault()
    1.19  {
    1.20 @@ -61,80 +64,92 @@
    1.21    return tid;
    1.22  }
    1.23  
    1.24 -//Model of interference calculation for FH-FSK wherein all nodes
    1.25 -//use an identical hopping pattern.  In this case, there is an (M-1)*SymbolTime
    1.26 -//clearing time between symbols transmitted on the same frequency.
    1.27 -//This clearing time combats ISI from channel delay spread and also has
    1.28 -//a byproduct of possibly reducing interference from other transmitted packets.
    1.29 -//double
    1.30 -//UanPhyCalcSinrFhFsk::CalcSinrDb(Ptr<Packet> pkt,
    1.31 -//                         Time arrTime,
    1.32 -//                         double rxPowerDb,
    1.33 -//                         double ambNoiseDb,
    1.34 -//                         UanTxMode mode,
    1.35 -//                         UanPdp pdp,
    1.36 -//                         const UanTransducer::ArrivalList &arrivalList) const
    1.37 -//{
    1.38 -//  if(mode.GetModType() == UanTxMode::OTHER)
    1.39 -//    NS_LOG_WARN("Calculating SINR for unsupported modulation type");
    1.40 -//
    1.41 -//
    1.42 -//
    1.43 -//
    1.44 -//  double intKp = -DbToKp(rxPowerDb); //This packet is in the arrivalList
    1.45 -//  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin();
    1.46 -//  for(;it != arrivalList.end();it++)
    1.47 -//    {
    1.48 -//      UanPdp intPdp = it->GetPdp();
    1.49 -//      double tDelta = arrTime.GetSeconds() - it->GetArrivalTime().GetSeconds();
    1.50 -//      //We want tDelta in terms of a single symbol (i.e. if tDelta = 7.3 symbol+clearing
    1.51 -//      //times, the offset in terms of the currently arriving symbol is still
    1.52 -//      //0.3 symbol+clearing times.
    1.53 -//      int16_t sign = (arrTime>0) ? 1 : -1;
    1.54 -//      double symTime = it->GetMode()->GetSymbolTime().GetSeconds() + it->GetMode()->GetClearingTime().GetSeconds();
    1.55 -//      int32_t syms = abs(tDelta / symTime);
    1.56 -//      tDelta = tDelta - sign*syms*symTime;
    1.57 -//
    1.58 -//      double power = 0.0;
    1.59 -//      if(tDelta > 0)
    1.60 -//        {
    1.61 -//          if(tDelta < mode.GetSymbolTime())
    1.62 -//            {
    1.63 -//              power += intPdp.SumTapsNc(0, mode->GetSymbolTime() - Seconds(tDelta));
    1.64 -//              power += intPdp.SumTapsNc(mode->GetSymbolTime() - Seconds(tDelta) + mode->GetClearingTime(),
    1.65 -//                                        2*mode->GetSymbolTime() - Seconds(tDelta) + mode->GetClearingTime());
    1.66 -//            }
    1.67 -//          else
    1.68 -//            {
    1.69 -//              Time start = mode->GetSymbolTime() + mode->GetClearingTime() - Seconds(tDelta);
    1.70 -//              Time end = start + mode->GetSymbolTime();
    1.71 -//              power += intPdp.SumTapsNc(start, end);
    1.72 -//
    1.73 -//              start = start + mode->GetSymbolTime() + mode->GetClearingTime();
    1.74 -//              end = start + mode->GetSymbolTime();
    1.75 -//              power += intPdp.SumTapsNc(start, end);
    1.76 -//            }
    1.77 -//        }
    1.78 -//      else
    1.79 -//        {
    1.80 -//          tDelta = abs(tDelta);
    1.81 -//          if(tDelta < mode->GetClearingTime())
    1.82 -//            {
    1.83 -//              Time start = Seconds(tDelta);
    1.84 -//              Time end = mode->GetSymbolTime();
    1.85 -//              power += intPdp.SumTapsNc(start, end);
    1.86 -//
    1.87 -//              Time
    1.88 -//            }
    1.89 -//        }
    1.90 -//      intKp += DbToKp(it->GetRxPowerDb());
    1.91 -//    }
    1.92 -//
    1.93 -//  double totalIntDb = KpToDb(intKp + DbToKp(ambNoiseDb));
    1.94 -//
    1.95 -//  NS_LOG_DEBUG("Calculating SINR:  RxPower = " << rxPowerDb << " dB.  Number of interferers = " << arrivalList.size() << "  Interference + noise power = " << totalIntDb << " dB.  SINR = " << rxPowerDb - totalIntDb << " dB.");
    1.96 -//  return rxPowerDb - totalIntDb;
    1.97 -//}
    1.98 +UanPhyCalcSinrFhFsk::UanPhyCalcSinrFhFsk()
    1.99 +{
   1.100 +
   1.101 +}
   1.102 +UanPhyCalcSinrFhFsk::~UanPhyCalcSinrFhFsk()
   1.103 +{
   1.104 +
   1.105 +}
   1.106 +
   1.107 +TypeId
   1.108 +UanPhyCalcSinrFhFsk::GetTypeId(void)
   1.109 +{
   1.110 +  static TypeId tid = TypeId("ns3::UanPhyCalcSinrFhFsk")
   1.111 +    .SetParent<Object>()
   1.112 +    .AddConstructor<UanPhyCalcSinrFhFsk>()
   1.113 +    .AddAttribute("NumberOfHops",
   1.114 +                  "Number of frequencies in hopping pattern",
   1.115 +                  UintegerValue(13),
   1.116 +                  MakeUintegerAccessor(&UanPhyCalcSinrFhFsk::m_hops),
   1.117 +                  MakeUintegerChecker<uint32_t>())
   1.118 +  ;
   1.119 +  return tid;
   1.120 +}
   1.121 +double
   1.122 +UanPhyCalcSinrFhFsk::CalcSinrDb(Ptr<Packet> pkt,
   1.123 +                         Time arrTime,
   1.124 +                         double rxPowerDb,
   1.125 +                         double ambNoiseDb,
   1.126 +                         UanTxMode mode,
   1.127 +                         UanPdp pdp,
   1.128 +                         const UanTransducer::ArrivalList &arrivalList) const
   1.129 +{
   1.130 +  if(mode.GetModType() != UanTxMode::FSK)
   1.131 +    NS_LOG_WARN("Calculating SINR for unsupported mode type");
   1.132 +
   1.133 +
   1.134 +
   1.135 +  double ts = 1.0 / mode.GetPhyRateSps();
   1.136 +  double clearingTime = (m_hops-1.0)*ts;
   1.137 +
   1.138 +  double effRxPowerDb = rxPowerDb + KpToDb(pdp.SumTapsNc(Seconds(0), Seconds(ts)));
   1.139 +  double isiKpa = DbToKp(rxPowerDb)*pdp.SumTapsNc(Seconds(ts+clearingTime), Seconds(2.0*ts+clearingTime));
   1.140 +
   1.141 +  UanTransducer::ArrivalList::const_iterator it = arrivalList.begin();
   1.142 +  double intKp = 0;
   1.143 +  for(;it != arrivalList.end();it++)
   1.144 +    {
   1.145 +      UanPdp intPdp = it->GetPdp();
   1.146 +      double tDelta = abs(arrTime.GetSeconds() - it->GetArrivalTime().GetSeconds());
   1.147 +      //We want tDelta in terms of a single symbol (i.e. if tDelta = 7.3 symbol+clearing
   1.148 +      //times, the offset in terms of the arriving symbol power is
   1.149 +      //0.3 symbol+clearing times.
   1.150 +
   1.151 +      int32_t syms = (uint32_t) ( (double) tDelta / (ts + clearingTime));
   1.152 +      tDelta = tDelta - syms*(ts + clearingTime);
   1.153 +
   1.154 +      if(arrTime  < it->GetArrivalTime())
   1.155 +        tDelta = ts+clearingTime - tDelta;
   1.156 +
   1.157 +      double intPower = 0.0;
   1.158 +      if(tDelta < ts)
   1.159 +        {
   1.160 +          intPower += intPdp.SumTapsNc(Seconds(0), Seconds(ts - tDelta));
   1.161 +          intPower += intPdp.SumTapsNc(Seconds(ts - tDelta + clearingTime),
   1.162 +                                       Seconds(2*ts - tDelta + clearingTime));
   1.163 +        }
   1.164 +      else
   1.165 +        {
   1.166 +          Time start = Seconds(ts + clearingTime - tDelta);
   1.167 +          Time end = start + Seconds(ts);
   1.168 +          intPower += intPdp.SumTapsNc(start, end);
   1.169 +
   1.170 +          start = start + Seconds(ts+clearingTime);
   1.171 +          end = start + Seconds(ts);
   1.172 +          intPower += intPdp.SumTapsNc(start, end);
   1.173 +        }
   1.174 +      intKp += DbToKp(it->GetRxPowerDb()) * intPower;
   1.175 +    }
   1.176 +
   1.177 +  double totalIntDb = KpToDb(isiKpa + intKp + DbToKp(ambNoiseDb));
   1.178 +
   1.179 +  NS_LOG_DEBUG("Calculating SINR:  RxPower = " << rxPowerDb << " dB.  Effective Rx power " << effRxPowerDb << " dB.  Number of interferers = " << arrivalList.size() << "  Interference + noise power = " << totalIntDb << " dB.  SINR = " << rxPowerDb - totalIntDb << " dB.");
   1.180 +  return effRxPowerDb - totalIntDb;
   1.181 +}
   1.182 +
   1.183 +
   1.184  
   1.185  double
   1.186  UanPhyCalcSinrDefault::CalcSinrDb(Ptr<Packet> pkt,
   1.187 @@ -157,7 +172,7 @@
   1.188  
   1.189    //The default ignores mode data and assumes that all rxpower transmitted is
   1.190    //captured by the receiver, and that all signal power associated with
   1.191 -  //interfering packets acts as additional noise.
   1.192 +  //interfering packets effects SINR identically to additional ambient noise.
   1.193  
   1.194    double intKp = -DbToKp(rxPowerDb); //This packet is in the arrivalList
   1.195    UanTransducer::ArrivalList::const_iterator it = arrivalList.begin();
   1.196 @@ -211,6 +226,95 @@
   1.197      }
   1.198  }
   1.199  
   1.200 +
   1.201 +UanPhyPerUmodem::UanPhyPerUmodem()
   1.202 +{
   1.203 +
   1.204 +}
   1.205 +UanPhyPerUmodem::~UanPhyPerUmodem()
   1.206 +{
   1.207 +
   1.208 +}
   1.209 +
   1.210 +TypeId UanPhyPerUmodem::GetTypeId(void)
   1.211 +{
   1.212 +  static TypeId tid =
   1.213 +      TypeId("ns3::UanPhyPerUmodem")
   1.214 +          .SetParent<Object> ()
   1.215 +          .AddConstructor<UanPhyPerUmodem> ()
   1.216 +      ;
   1.217 +  return tid;
   1.218 +}
   1.219 +
   1.220 +double
   1.221 +UanPhyPerUmodem::nchoosek(uint32_t n, uint32_t k)
   1.222 +{
   1.223 +  double result;
   1.224 +
   1.225 +    result=1.0;
   1.226 +
   1.227 +    for (uint32_t i = std::max(k,n-k) + 1; i <= n; ++i)
   1.228 +            result *= i;
   1.229 +
   1.230 +    for (uint32_t i = 2; i <= std::min(k,n-k); ++i)
   1.231 +            result /= i;
   1.232 +
   1.233 +    return result;
   1.234 +}
   1.235 +
   1.236 +double
   1.237 +UanPhyPerUmodem::CalcPer(double sinr, UanTxMode mode)
   1.238 +{
   1.239 +  uint32_t d[] =
   1.240 +    { 12, 14, 16, 18, 20, 22, 24, 26, 28 };
   1.241 +  double Bd[] =
   1.242 +    { 33, 281, 2179, 15035LLU, 105166LLU, 692330LLU, 4580007LLU, 29692894LLU,
   1.243 +      190453145LLU };
   1.244 +
   1.245 +  //double Rc = 1.0 / 2.0;
   1.246 +  double ebno = std::pow(10.0, sinr / 10.0);
   1.247 +  double perror = 1.0 / (2.0 + ebno);
   1.248 +  double P[9];
   1.249 +
   1.250 +  if (sinr >= 10)
   1.251 +    return 0;
   1.252 +  if (sinr <= 6)
   1.253 +    return 1;
   1.254 +
   1.255 +  for (uint32_t r = 0; r < 9; r++)
   1.256 +    {
   1.257 +      double sumd = 0;
   1.258 +      for (uint32_t k = 0; k < d[r]; k++)
   1.259 +        {
   1.260 +          sumd = sumd + nchoosek(d[r] - 1 + k, k) * std::pow(1 - perror, (double) k);
   1.261 +        }
   1.262 +      P[r] = std::pow(perror, (double) d[r]) * sumd;
   1.263 +
   1.264 +    }
   1.265 +
   1.266 +  double Pb = 0;
   1.267 +  for (uint32_t r = 0; r < 8; r++)
   1.268 +    {
   1.269 +      Pb = Pb + Bd[r] * P[r];
   1.270 +    }
   1.271 +
   1.272 +  //cout << "Pb = " << Pb << endl;
   1.273 +
   1.274 +  double Ppacket = 1;
   1.275 +  double temp = nchoosek(288, 0);
   1.276 +  temp *= std::pow((1 - Pb), 288.0);
   1.277 +  Ppacket -= temp;
   1.278 +  temp = nchoosek(288, 1) * Pb * std::pow((1 - Pb), 287);
   1.279 +  Ppacket -= temp;
   1.280 +
   1.281 +  //NS_LOG_DEBUG("Pb = " << Pb << " Prob of Packet error = " << Ppacket);
   1.282 +
   1.283 +  if (Ppacket > 1)
   1.284 +    return 1;
   1.285 +  else
   1.286 +    return Ppacket;
   1.287 +}
   1.288 +
   1.289  UanModesList
   1.290  UanPhyGen::GetDefaultModes(void)
   1.291  {
     2.1 --- a/src/devices/uan/uan-phy-gen.h	Wed Apr 01 01:35:43 2009 -0700
     2.2 +++ b/src/devices/uan/uan-phy-gen.h	Wed Apr 01 16:00:30 2009 -0700
     2.3 @@ -34,9 +34,8 @@
     2.4  /**
     2.5   * \class UanPhyPerGenDefault
     2.6   * \brief Default Packet Error Rate calculator for UanPhyGen
     2.7 - * This class uses basic probability of error equations learned
     2.8 - * in any wireless comms course.  Not accurate for
     2.9 - * underwater.
    2.10 + * Considers no error if SINR is > user defined threshold
    2.11 + * (configured by an attribute).
    2.12   */
    2.13  class UanPhyPerGenDefault : public UanPhyPer
    2.14  {
    2.15 @@ -52,6 +51,24 @@
    2.16  };
    2.17  
    2.18  /**
    2.19 + * \class UanPhyPerUmodem
    2.20 + * \brief Packet error rate calculation assuming WHOI Micromodem like PHY
    2.21 + * Calculates PER assuming rate 1/2 convolutional code with constraint length 9
    2.22 + * with soft decision viterbi decoding and a CRC capable of correcting 1 bit error
    2.23 + */
    2.24 +class UanPhyPerUmodem : public UanPhyPer
    2.25 +{
    2.26 +public:
    2.27 +  UanPhyPerUmodem();
    2.28 +  virtual ~UanPhyPerUmodem();
    2.29 +
    2.30 +  static TypeId GetTypeId(void);
    2.31 +  virtual double CalcPer(double sinrDb, UanTxMode mode);
    2.32 +private:
    2.33 +  double nchoosek(uint32_t n, uint32_t k);
    2.34 +
    2.35 +};
    2.36 +/**
    2.37   * \class UanPhyCalcSinrDefault
    2.38   * \brief Default SINR calculator for UanPhyGen
    2.39   */
    2.40 @@ -73,6 +90,34 @@
    2.41  };
    2.42  
    2.43  /**
    2.44 + * \class UanPhyCalcSinrFhFsk
    2.45 + * \brief WHOI Micromodem like FH-FSK model
    2.46 + *
    2.47 + * Model of interference calculation for FH-FSK wherein all nodes
    2.48 + * use an identical hopping pattern.  In this case, there is an (M-1)*SymbolTime
    2.49 + * clearing time between symbols transmitted on the same frequency.
    2.50 + * This clearing time combats ISI from channel delay spread and also has
    2.51 + * a byproduct of possibly reducing interference from other transmitted packets.
    2.52 + */
    2.53 +class UanPhyCalcSinrFhFsk : public UanPhyCalcSinr
    2.54 +{
    2.55 +
    2.56 +public:
    2.57 +  UanPhyCalcSinrFhFsk();
    2.58 +  virtual ~UanPhyCalcSinrFhFsk();
    2.59 +  static TypeId GetTypeId(void);
    2.60 +  virtual double CalcSinrDb(Ptr<Packet> pkt,
    2.61 +                         Time arrTime,
    2.62 +                         double rxPowerDb,
    2.63 +                         double ambNoiseDb,
    2.64 +                         UanTxMode mode,
    2.65 +                         UanPdp pdp,
    2.66 +                         const UanTransducer::ArrivalList &arrivalList
    2.67 +                         ) const;
    2.68 +  uint32_t m_hops;
    2.69 +};
    2.70 +
    2.71 +/**
    2.72   * \class UanPhyGen
    2.73   * \brief Generic PHY model
    2.74   */
     3.1 --- a/src/devices/uan/uan-tx-mode.h	Wed Apr 01 01:35:43 2009 -0700
     3.2 +++ b/src/devices/uan/uan-tx-mode.h	Wed Apr 01 16:00:30 2009 -0700
     3.3 @@ -115,7 +115,10 @@
     3.4  
     3.5  };
     3.6  
     3.7 -
     3.8 +/**
     3.9 + * \class UanModesList
    3.10 + * \brief Container for UanTxModes
    3.11 + */
    3.12  class UanModesList : public ns3::Object
    3.13  {
    3.14  public:
    3.15 @@ -123,9 +126,23 @@
    3.16    virtual ~UanModesList();
    3.17    static TypeId GetTypeId(void);
    3.18  
    3.19 +  /**
    3.20 +   * \param mode Add mode to list
    3.21 +   */
    3.22    void AppendMode(UanTxMode mode);
    3.23 +  /**
    3.24 +   * \brief delete mode at given index
    3.25 +   * \param num Index of mode to delete
    3.26 +   */
    3.27    void DeleteMode(uint32_t num);
    3.28 +  /**
    3.29 +   * \param index Mode index
    3.30 +   * \returns mode at given index
    3.31 +   */
    3.32    UanTxMode operator[](uint32_t index) const;
    3.33 +  /**
    3.34 +   * \returns Number of modes in list
    3.35 +   */
    3.36    uint32_t GetNModes(void) const;
    3.37  
    3.38