User Manual, Developers Guide and API Documentation

ErrorModelling.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  * WiMeMac                                                                    *
00003  * This file is part of openWNS (open Wireless Network Simulator)
00004  * _____________________________________________________________________________
00005  *
00006  * Copyright (C) 2004-2011
00007  * Chair of Communication Networks (ComNets)
00008  * Kopernikusstr. 5, D-52074 Aachen, Germany
00009  * phone: ++49-241-80-27910,
00010  * fax: ++49-241-80-22242
00011  * email: info@openwns.org
00012  * www: http://www.openwns.org
00013  * _____________________________________________________________________________
00014  *
00015  * openWNS is free software; you can redistribute it and/or modify it under the
00016  * terms of the GNU Lesser General Public License version 2 as published by the
00017  * Free Software Foundation;
00018  *
00019  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00020  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00021  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00022  * details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00026  *
00027  ******************************************************************************/
00028 
00029 #include <WIMEMAC/convergence/PhyMode.hpp>
00030 #include <WIMEMAC/convergence/ErrorModelling.hpp>
00031 #include <WIMEMAC/lowerMAC/Manager.hpp>
00032 #include "IPhyServices.hpp"
00033 
00034 using namespace wimemac::convergence;
00035 
00036 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00037     wimemac::convergence::ErrorModelling,
00038     wns::ldk::FunctionalUnit,
00039     "wimemac.convergence.ErrorModelling",
00040     wns::ldk::FUNConfigCreator);
00041 
00042 
00043 ErrorModelling::ErrorModelling(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config) :
00044     wns::ldk::fu::Plain<ErrorModelling, ErrorModellingCommand>(fun),
00045     config(_config),
00046     logger(config.get<wns::pyconfig::View>("logger")),
00047     phyUserCommandName(config.get<std::string>("phyUserCommandName")),
00048     phyUserName(config.get<std::string>("phyUserName")),
00049     managerName(config.get<std::string>("managerName")),
00050     managerCommandName(config.get<std::string>("managerCommandName")),
00051     dis(),
00052     perProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), "wimemac.errormodelling.PER"))
00053 {
00054 
00055     // read the localIDs from the config
00056     wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection());
00057 
00058     for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii)
00059     {
00060         std::string key = config.get<std::string>("localIDs.keys()",ii);
00061         unsigned long int value  = config.get<unsigned long int>("localIDs.values()",ii);
00062         localContext.addProvider( wns::probe::bus::contextprovider::Constant(key, value) );
00063     }
00064 
00065     lossRatio = wns::probe::bus::collector(localContext, config, "lossRatioProbeName");
00066 
00067 
00068     // Fill the error mapping from the config
00069     wns::pyconfig::View configview = config.getView("snr2pmean_100");
00070     for(int i = 0; i < configview.len("mapping"); ++i)
00071     {
00072         wns::pyconfig::View mo = configview.getView("mapping", i);
00073         if(i == (configview.len("mapping") - 1))
00074         {
00075             snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00076         }
00077         else
00078         {
00079             if(i == 0)
00080             {
00081                 snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00082             }
00083             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00084             snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00085         }
00086     }
00087 
00088     configview = config.getView("snr2pmean_150");
00089     for(int i = 0; i < configview.len("mapping"); ++i)
00090     {
00091         wns::pyconfig::View mo = configview.getView("mapping", i);
00092         if(i == (configview.len("mapping") - 1))
00093         {
00094             snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00095         }
00096         else
00097         {
00098             if(i == 0)
00099             {
00100                 snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00101             }
00102             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00103             snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00104         }
00105     }
00106 
00107     configview = config.getView("snr2pmean_200");
00108     for(int i = 0; i < configview.len("mapping"); ++i)
00109     {
00110         wns::pyconfig::View mo = configview.getView("mapping", i);
00111         if(i == (configview.len("mapping") - 1))
00112         {
00113             snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00114         }
00115         else
00116         {
00117             if(i == 0)
00118             {
00119                 snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00120             }
00121             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00122             snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00123         }
00124     }
00125 
00126     configview = config.getView("snr2pmean_300");
00127     for(int i = 0; i < configview.len("mapping"); ++i)
00128     {
00129         wns::pyconfig::View mo = configview.getView("mapping", i);
00130         if(i == (configview.len("mapping") - 1))
00131         {
00132             snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00133         }
00134         else
00135         {
00136             if(i == 0)
00137             {
00138                 snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00139             }
00140             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00141             snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00142         }
00143     }
00144 
00145     configview = config.getView("snr2pmean_375");
00146     for(int i = 0; i < configview.len("mapping"); ++i)
00147     {
00148         wns::pyconfig::View mo = configview.getView("mapping", i);
00149         if(i == (configview.len("mapping") - 1))
00150         {
00151             snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00152         }
00153         else
00154         {
00155             if(i == 0)
00156             {
00157                 snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00158             }
00159             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00160             snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00161         }
00162     }
00163 
00164     configview = config.getView("snr2pmean_600");
00165     for(int i = 0; i < configview.len("mapping"); ++i)
00166     {
00167         wns::pyconfig::View mo = configview.getView("mapping", i);
00168         if(i == (configview.len("mapping") - 1))
00169         {
00170             snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00171         }
00172         else
00173         {
00174             if(i == 0)
00175             {
00176                 snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00177             }
00178             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00179             snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00180         }
00181     }
00182 
00183 
00184     configview = config.getView("snr2pmean_750");
00185     for(int i = 0; i < configview.len("mapping"); ++i)
00186     {
00187         wns::pyconfig::View mo = configview.getView("mapping", i);
00188         if(i == (configview.len("mapping") - 1))
00189         {
00190             snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00191         }
00192         else
00193         {
00194             if(i == 0)
00195             {
00196                 snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00197             }
00198             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00199             snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00200         }
00201     }
00202 
00203     configview = config.getView("snr2pmean_900");
00204     for(int i = 0; i < configview.len("mapping"); ++i)
00205     {
00206         wns::pyconfig::View mo = configview.getView("mapping", i);
00207         if(i == (configview.len("mapping") - 1))
00208         {
00209             snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean"));
00210         }
00211         else
00212         {
00213             if(i == 0)
00214             {
00215                 snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1);
00216             }
00217             wns::pyconfig::View nextMo = configview.getView("mapping", i+1);
00218             snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean"));
00219         }
00220     }
00221 }
00222 
00223 void ErrorModelling::onFUNCreated()
00224 {
00225     friends.phyuser = getFUN()->findFriend<wimemac::convergence::IPhyServices*>(phyUserName);
00226     friends.manager = getFUN()->findFriend<wimemac::lowerMAC::IManagerServices*>(managerName);
00227 
00228     // Fill the registry with the snr2pmean maps together with their corresponding phymodes as key
00229     // get lowest phymode and start filling the registry
00230     wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode(friends.phyuser->getPhyModeProvider()->getDefaultPhyMode());
00231     assure(friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_), "Couldn't retrieve the lowest MCS");
00232     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_100_);
00233 
00234     // get the next higher MCS and proceed
00235     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00236     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00237     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_150_);
00238 
00239     // get the next higher MCS and proceed
00240     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00241     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00242     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_200_);
00243 
00244     // get the next higher MCS and proceed
00245     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00246     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00247     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_300_);
00248 
00249     // get the next higher MCS and proceed
00250     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00251     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00252     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_375_);
00253 
00254     // get the next higher MCS and proceed
00255     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00256     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00257     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_600_);
00258 
00259     // get the next higher MCS and proceed
00260     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00261     assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined");
00262     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_750_);
00263 
00264     // get the next higher MCS and proceed
00265     friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00266     assure(friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too many MCSs defined");
00267     snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_900_);
00268 }
00269 
00270 void ErrorModelling::processIncoming(const wns::ldk::CompoundPtr& compound)
00271 {
00272 
00273     // Calculate PER
00274     
00275     wns::Power rxPower_ = friends.phyuser->getRxPower(compound->getCommandPool());
00276     wns::Power interference_ = friends.phyuser->getInterference(compound->getCommandPool());
00277 
00278     wns::Ratio sinr_ = wns::Ratio::from_dB(rxPower_.get_dBm() - interference_.get_dBm());
00279 
00280     //MESSAGE_BEGIN(NORMAL, logger, m, "DEBUG : Errormodelling " << sinr_);
00281     //m << " | rx " << rxPower_;
00282     //m << " | interference " << interference_;
00283     //MESSAGE_END();
00284 
00285     wimemac::convergence::PhyMode phyMode_ = friends.manager->getPhyMode(compound->getCommandPool());
00286 
00287     ErrorModellingCommand* emc = activateCommand(compound->getCommandPool());
00288     emc->local.sinr = sinr_;
00289 
00290     float pmean_ = NULL;
00291 
00292     SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS());
00293 
00294     if (!snr2pmeanMap_->has(float(sinr_.get_dB())))
00295     {
00296         if(sinr_.get_dB() < -10) pmean_ = 0;
00297         else if(sinr_.get_dB() > 100) pmean_ = snr2pmeanMap_->get(float(sinr_.get_dB()));
00298         else
00299         {
00300             // Needed to prevent rangemap bug if asking for an INT value
00301             MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR before" << sinr_.get_dB());
00302             sinr_.set_dB(sinr_.get_dB() + 0.001);
00303             MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB());
00304         }
00305     }
00306     else pmean_ = snr2pmeanMap_->get(float(sinr_.get_dB()));
00307 
00308     // get frame length; check if compound is preamble or psdu
00309     Bit compsize_ = compound->getLengthInBits();
00310 
00311     double q = 1 / (pmean_ - 7 + 2); // K = 7 is constraint length of the convolutional code
00312     if (pmean_ - 7 + 2 <= 0) q = 1;
00313     emc->local.per = 1 - pow( (1 - q), (compsize_-(7-1)) );
00314 
00315     // If rxPower is below the minimum rxPower set PER = 1
00316     if (rxPower_ < friends.manager->getPhyMode(compound->getCommandPool()).getMinRxPower())
00317         emc->local.per = 1;
00318 
00319     // Put per into probe if it's a payload compound
00320     if (!friends.manager->isPreamble(compound->getCommandPool()) &&
00321         !friends.manager->isBeacon(compound->getCommandPool()) &&
00322         friends.manager->isForMe(compound->getCommandPool()))
00323         perProbe_->put(compound, emc->local.per);
00324 
00325 
00326     wns::service::dll::UnicastAddress tx = friends.manager->getTransmitterAddress(compound->getCommandPool());
00327     MESSAGE_BEGIN(NORMAL, logger, m, "New compound with SNR " << sinr_);
00328     m << " | CompSize " << compsize_;
00329     m << " | NIBP6S " << phyMode_.getInfoBitsPer6Symbols();
00330     m << " | Pmean " << pmean_;
00331     m << " | PER " << emc->local.per;
00332     m << " | from address " << tx;
00333     MESSAGE_END();
00334 
00335     // Mark compound according to per evaluation
00336     if(!lastPreambleWasDecoded.knows(tx)) lastPreambleWasDecoded.insert(tx, false);
00337     if ( dis() < emc->local.per ){
00338 
00339         if (lossRatio != NULL)
00340         {
00341             lossRatio->put(compound, 1);
00342         }
00343         emc->local.checkOK = false;
00344         MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00345         m << " CRCheck - failed - compound marked";
00346         MESSAGE_END();
00347 
00348         if (friends.manager->isPreamble(compound->getCommandPool()))
00349             lastPreambleWasDecoded.update(tx, false);
00350     }
00351     else
00352     {
00353         if (friends.manager->isPreamble(compound->getCommandPool()))
00354         {
00355             lastPreambleWasDecoded.update(tx, true);
00356             emc->local.checkOK = true;
00357         }
00358         else
00359         {
00360             // Check if before received preamble could be decoded, otherwise mark payload compound as bad
00361             if(lastPreambleWasDecoded.find(tx) == true)
00362             {
00363                 emc->local.checkOK = true;
00364                 if (lossRatio != NULL)
00365                 {
00366                     lossRatio->put(compound, 0);
00367                 }
00368                 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00369                 m << " CRCheck - success";
00370                 MESSAGE_END();
00371 
00372             }
00373             else
00374             {
00375                 emc->local.checkOK = false;
00376                 if (lossRatio != NULL)
00377                 {
00378                     lossRatio->put(compound, 1);
00379                 }
00380                 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00381                 m << " CRCheck - failed because of bad preamble - compound marked";
00382                 MESSAGE_END();
00383             }
00384         }
00385 
00386     }
00387 
00388 }
00389 
00390 void ErrorModelling::processOutgoing(const wns::ldk::CompoundPtr& /*compound*/)
00391 {
00392     //MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName());
00393     //m << " passing through Errormodelling outgoing";
00394     //MESSAGE_END();
00395 }
00396 
00397 wimemac::convergence::MCS
00398 ErrorModelling::getMaxPosMCS(wns::Ratio sinr_, Bit maxCompoundSize_, double per_)
00399 {
00400     // Calculate minimum allowed pmean
00401     double pow_ = pow( (1-per_) , (1 / ((double)maxCompoundSize_ - 7 + 1)) );
00402     float pmean_ = 7 - 2 + 1 / ( 1 - pow_ );
00403 
00404     // Search through the mapping registry for the highest MCS with a pmean greater than the calculated one
00405     wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode(friends.phyuser->getPhyModeProvider()->getDefaultPhyMode());
00406     assure(friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_), "Couldn't retrieve the lowest MCS");
00407 
00408     bool foundMax_ = false;
00409     while (!foundMax_)
00410     {
00411         SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS());
00412         // Check if pmean for this MCS and SNR is greater than the min pmean
00413 
00414         float pmeanMapped_;
00415         if (!snr2pmeanMap_->has(float(sinr_.get_dB())))
00416         {
00417             if(sinr_.get_dB() < -10) pmeanMapped_ = 0;
00418             else if(sinr_.get_dB() > 100) pmeanMapped_ = snr2pmeanMap_->get(float(sinr_.get_dB()));
00419             // Needed to prevent rangemap bug if asking for an INT value
00420             sinr_.set_dB(sinr_.get_dB() + 0.001);
00421             MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB());
00422         }
00423         else pmeanMapped_ = snr2pmeanMap_->get(float(sinr_.get_dB()));
00424 
00425         if(pmean_ <= pmeanMapped_)
00426         {
00427             // Is the maximum MCS reached -> use this
00428             if(friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_))
00429             {
00430                 foundMax_ = true;
00431             }
00432             // Increment MCS to check if next one also meets the min pmean
00433             else friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_);
00434         }
00435         else
00436         {
00437             // The MCS did not meet the requirements -> use next lower MCS
00438             if (friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_))
00439             {
00440                 MESSAGE_SINGLE(NORMAL, logger, "LinkEval : Even lowest PhyMode is not sufficient! Returning lowest MCS to proceed");
00441             }
00442             else friends.phyuser->getPhyModeProvider()->mcsDown(phyMode_);
00443             foundMax_ = true;
00444         }
00445     }
00446 
00447     // MESSAGE_SINGLE(NORMAL, logger, "Calculate MaxMCS : " <<" Returning Phymode with "<< phyMode_.getDataRate() << " MBit/s" );
00448     return phyMode_.getMCS();
00449 }
00450 
00451 double 
00452 ErrorModelling::getErrorRateForCommandFrames(wns::Ratio sinr_, Bit maxCompoundSize_)
00453 {
00454    
00455   float pmean;
00456   wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode();
00457   SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS());
00458 
00459     if (!snr2pmeanMap_->has(float(sinr_.get_dB())))
00460     {
00461         if(sinr_.get_dB() < -10) pmean = 0;
00462         else if(sinr_.get_dB() > 100) pmean = snr2pmeanMap_->get(float(sinr_.get_dB()));
00463         else
00464         {
00465             // Needed to prevent rangemap bug if asking for an INT value
00466             MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR before" << sinr_.get_dB());
00467             sinr_.set_dB(sinr_.get_dB() + 0.001);
00468             MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB());
00469         }
00470     }
00471     else pmean = snr2pmeanMap_->get(float(sinr_.get_dB()));
00472 
00473         double q = 1 / (pmean - 7 + 2); // K = 7 is constraint length of the convolutional code
00474     if (pmean - 7 + 2 <= 0) q = 1;
00475     return(1 - pow( (1 - q), (maxCompoundSize_-(7-1)) ));
00476 }

Generated on Sun May 27 03:32:06 2012 for openWNS by  doxygen 1.5.5