User Manual, Developers Guide and API Documentation

Beamforming.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <RISE/stations/station.hpp>
00029 #include <RISE/transmissionobjects/transmissionobjectbf.hpp>
00030 #include <RISE/antenna/Beamforming.hpp>
00031 #include <WNS/rng/RNGen.hpp>
00032 #include <boost/numeric/ublas/blas.hpp>
00033 #include <boost/numeric/ublas/lu.hpp>
00034 
00035 #include <cmath>
00036 #include <algorithm>
00037 #include <fstream>
00038 
00039 using namespace rise::antenna;
00040 
00041 Beamforming::Beamforming(const wns::pyconfig::View& pyConfigView,
00042                          Station* const station)
00043     : Antenna(pyConfigView, station),
00044       pd_noAntennaElements(1),
00045       pd_lastPowerReceived(),
00046       pd_receivedTO2PatternMap(),
00047       arrayLayout(linear),
00048       positionErrorVariance(pyConfigView.get<double>("positionErrorVariance")),
00049       dis(0.0, positionErrorVariance, wns::simulator::getRNG())
00050 
00051 {
00052     pd_noAntennaElements = pyConfigView.get<long int>("noOfElements");
00053     if (pyConfigView.get<std::string>("arrayLayout") == "circular")
00054         arrayLayout = circular;
00055 
00056     if (drawPattern == true)
00057         drawRadiationPattern();
00058 
00059     MESSAGE_BEGIN(NORMAL, log, m,"Beamforming antenna initiated with layout (linear=0): ");
00060     m << arrayLayout << ", " << pd_noAntennaElements <<  " elements, and "
00061       << positionErrorVariance << " variance in position estimation";
00062     MESSAGE_END();
00063 
00064     // Create the steervectors for all 360 degrees once and for all These
00065     // steervectors only depend on the geometry of the array (noAntennaElements,
00066     // ArrayLayout) which is known once the BF antenna is created.
00067     steervectors.resize(360, 0);
00068 
00069     for (unsigned long int i = 0; i < 360; i++)
00070     {
00071         steervectors[i] = new boost::numeric::ublas::vector<std::complex<double> >(pd_noAntennaElements);
00072         for (unsigned long int j = 0; j < pd_noAntennaElements; j++)
00073         {
00074             // Now I have to add pi here!?
00075             std::complex<double> c = std::polar(1.0, calculatePhaseDelta(j, double(i)*M_PI/180+M_PI)); 
00076             (*steervectors[i])(j) = c;
00077         }
00078     }
00079 }
00080 
00081 Beamforming::~Beamforming()
00082 {
00083     for (unsigned long int i = 0; i < 360; ++i)
00084     {
00085         delete steervectors[i];
00086     }
00087     pd_receivedTO2PatternMap.clear();
00088 }
00089 
00090 wns::Ratio
00091 Beamforming::getGain(const wns::Position& pos,
00092                      const TransmissionObjectPtr& TO) const
00093 {
00094     TO2PatternMap::const_iterator itr = pd_receivedTO2PatternMap.find(TO);
00095     assure(itr != pd_receivedTO2PatternMap.end(), "The TransmissionObject is not registered for receiving at this antenna!");
00096     return getGain(pos, itr->second);
00097 }
00098 
00099 wns::Ratio
00100 Beamforming::getGain(const wns::Position& pos,
00101                      PatternPtr pattern) const
00102 {
00103     double phi = (pos - getPosition()).getAzimuth();
00104     if (phi < 0) phi += M_PI + M_PI;
00105     unsigned long int index = (unsigned long int)(180 * phi / M_PI + 0.5); // 0.5 to round
00106     if(index == 360) index = 0;
00107     assure(index < pattern->getSize(), "pattern index out of range");
00108 
00109     wns::Ratio a_directivity = pd_getGainEntry(index, pattern);
00110     MESSAGE_BEGIN(VERBOSE, log, m,"Directivity in (");
00111     m << pos.getX() << "," << pos.getY() <<  "," << pos.getZ() << "): " << a_directivity.get_dB();
00112     MESSAGE_END();
00113     return a_directivity;
00114 }
00115 
00116 wns::Ratio
00117 Beamforming:: pd_getGainEntry(unsigned long int index,
00118                               PatternPtr pattern) const
00119 {
00120     assure(index < pattern->getSize(), "pattern index out of range");
00121     double t = pattern->pattern.at(index);
00122     return wns::Ratio::from_factor(t*t);
00123 }
00124 
00125 void
00126 Beamforming::setPowerReceivedForStation(Station* const id,
00127                                         const wns::Power power)
00128 {
00129     pd_lastPowerReceived[id] = power;
00130 }
00131 
00132 void
00133 Beamforming::setTxPowerForStation(Station* const id,
00134                                   const wns::Power power)
00135 {
00136     pd_lastTxPower[id] = power;
00137 }
00138 
00139 void
00140 Beamforming::startReceiving(const TransmissionObjectPtr& TO,
00141                             PatternPtr pattern)
00142 {
00143     pd_receivedTO2PatternMap[TO] = pattern;
00144 }
00145 
00146 void
00147 Beamforming::stopReceiving(const TransmissionObjectPtr& TO)
00148 {
00149     pd_receivedTO2PatternMap.erase(pd_receivedTO2PatternMap.find(TO));
00150 }
00151 
00152 std::map<rise::Station*, wns::CandI>
00153 Beamforming::calculateCandIsTx(const std::map<Station*, wns::Power>& station2iIntercellPlusNoise,
00154                                wns::Power xFriendlyness,
00155                                wns::Power txPower,
00156                                bool eirpLimited)
00157 {
00158     // SINR estimation in Tx case, in other words does the following: how much
00159     // do I interfere station A when I send simultaniously to all the other
00160     // stations from the given combination (B, C,...). This means that in the
00161     // calculation of SINR for station A, the following values, or its estimations
00162     // should be used:
00163 
00164     //      Tx power for X + pathloss from me to A + X's pattern towards A,
00165 
00166     // where X traverses all the stations from the given combination: in case X = A
00167     // the value is signal strength, and if they are different the value is summed
00168     // to interference.
00169 
00170     std::vector<Station*> combination;
00171     for(std::map<Station*, wns::Power>::const_iterator itr = station2iIntercellPlusNoise.begin();
00172         itr != station2iIntercellPlusNoise.end();
00173         itr ++)
00174     {
00175         combination.push_back(itr->first);
00176     }
00177     std::map <Station*, PatternPtr > outpattern;
00178     std::vector<Station*>::const_iterator s;
00179     for (s = combination.begin(); s != combination.end(); s++)
00180     {
00181         std::vector<Station*> undesired = combination;
00182         undesired.erase(std::find(undesired.begin(), undesired.end(), *s));
00183         outpattern[*s] = p_calculateBeam(*s, undesired, xFriendlyness);
00184     }
00185 
00186     double txPowerReduction = 0.0;
00187     if(eirpLimited){
00188         // if required, the txPower is restricted to the EIRP
00189         wns::service::phy::ofdma::SumPattern sumPattern;
00190         assure(sumPattern.getSize() == 0, "new sum Pattern is not empty");
00191         assure(!combination.empty(), "combination is empty");
00192         for (s = combination.begin(); s != combination.end(); s++) {
00193             MESSAGE_SINGLE(VERBOSE, log, "maximum gain of pattern to add: " << outpattern[*s]->getMaxGain());
00194             sumPattern.add(outpattern[*s]);
00195             MESSAGE_SINGLE(VERBOSE, log, "current maximum gain of pattern: " << sumPattern.getMaxGain());
00196         }
00197         txPowerReduction = sumPattern.getMaxGain().get_factor();
00198         MESSAGE_SINGLE(NORMAL, log, "Tx power reduction per concurrent stream due to EIRP 1/" << txPowerReduction);
00199     }
00200     else if (!eirpLimited){
00201         // in SDMA, the txPower of the antenna is equally distributed to all
00202         // concurrent streams
00203         txPowerReduction = combination.size()*1.0;
00204         MESSAGE_SINGLE(NORMAL, log, "Tx power reduction per concurrent stream is 1/" << txPowerReduction);
00205     }
00206 
00207     std::map<rise::Station*, wns::CandI > candis;
00208 
00209     for (s = combination.begin(); s != combination.end(); s++)
00210     {
00211         double signal = 0.0;
00212         double iIntra = 0.0;
00213 
00214         // the angle is fixed, traverse the patterns
00215         unsigned long int grad = (unsigned long int)(pd_azimuthAngles[*s]*180/M_PI + 0.5); //0.5 to round
00216         if (grad == 360) grad = 0;
00217         assure(grad < outpattern[*s]->getSize(), "pattern index (grad) out of range");
00218 
00219         float pathloss = pd_lastTxPower[*s].get_mW() / pd_lastPowerReceived[*s].get_mW();
00220 
00221         for (std::vector<Station*>::const_iterator interferer = combination.begin(); interferer != combination.end(); interferer++)
00222         {
00223             assure(pd_lastTxPower.find(*interferer) != pd_lastTxPower.end(),
00224                    "TX power of station not yet registred at this antenna!");
00225 
00226             if ((*s) == (*interferer))
00227                 signal = outpattern[*s]->pattern.at(grad) * outpattern[*s]->pattern.at(grad) *
00228                     txPower.get_mW() / pathloss / txPowerReduction;
00229             else
00230                 iIntra += outpattern[*interferer]->pattern.at(grad) * outpattern[*interferer]->pattern.at(grad) *
00231                     txPower.get_mW() / pathloss / txPowerReduction;
00232         }
00233 
00234         // sum up entire interference
00235         double interference = 0.0;
00236         // add inter-cell interference and noise
00237         interference += station2iIntercellPlusNoise.find(*s)->second.get_mW();
00238         // add intra-cell interference
00239         interference += iIntra;
00240 
00241         assure(interference > 0.0, "Interference + Noise is not positive!");
00242         assure(signal > 0.0, "Carrier Signal is not greater than zero!");
00243 
00244         //return value
00245         wns::CandI candi = wns::CandI();
00246         candi.sdma.iIntra = wns::Power::from_mW(iIntra);
00247         candi.C = wns::Power::from_mW(signal);
00248         candi.I = wns::Power::from_mW(interference);
00249         candis[*s] = candi;
00250     }
00251     return candis;
00252 }
00253 
00254 
00255 std::map<rise::Station*, wns::CandI >
00256 Beamforming::calculateCandIsRx(const std::vector<Station*>& combination,
00257                               wns::Power iInterPlusNoise)
00258 {
00259     assure(iInterPlusNoise.get_mW() > 0.0, "given interference plus noise is not positive!");
00260 
00261     std::map <Station*, PatternPtr > outpattern;
00262     std::vector<Station*>::const_iterator s;
00263     for (s = combination.begin(); s != combination.end(); s++)
00264     {
00265         std::vector<Station*> undesired = combination;
00266         undesired.erase(std::find(undesired.begin(), undesired.end(), *s));
00267         // in order to calculate the perfect beam, which seems to be
00268         // unrealistic, only the inter-cell interference should be given to
00269         // calculate the beam
00270         outpattern[*s] = p_calculateBeam(*s, undesired, iInterPlusNoise);
00271     }
00272 
00273     std::map<rise::Station*, wns::CandI > candis;
00274 
00275     for (s = combination.begin(); s != combination.end(); s++)
00276     {
00277         double signal = 0.0;
00278         double iIntra = 0.0;
00279 
00280         unsigned long int grad = 0;
00281         // the pattern is fixed, angles change
00282         for (std::vector<Station*>::const_iterator interferer = combination.begin(); interferer != combination.end(); interferer++)
00283         {
00284             grad = (unsigned long int)(pd_azimuthAngles[*interferer]*180/M_PI +0.5); //0.5 to round
00285             if(grad == 360) grad = 0;
00286             assure(grad < outpattern[*s]->getSize(), "pattern index (grad) out of range");
00287 
00288             if ((*s) == (*interferer))
00289             {
00290                 MESSAGE_BEGIN(VERBOSE, log, m, "");
00291                 m << "amplitude factor to desired station: " << outpattern[*s]->pattern.at(grad);
00292                 MESSAGE_END();
00293                 signal = outpattern[*s]->pattern.at(grad) * outpattern[*s]->pattern.at(grad) * pd_lastPowerReceived[*s].get_mW();
00294             }
00295             else
00296             {
00297                 MESSAGE_BEGIN(VERBOSE, log, m, "");
00298                 m << "amplitude factor to interferer: " << outpattern[*s]->pattern.at(grad);
00299                 MESSAGE_END();
00300                 iIntra += outpattern[*s]->pattern.at(grad) * outpattern[*s]->pattern.at(grad) * pd_lastPowerReceived[*interferer].get_mW();
00301             }
00302         }
00303         //sum up the entire interference
00304         double interference = 0.0;
00305         // add omni-directional interference and noise
00306         interference += iInterPlusNoise.get_mW();
00307         //add intra-cell interference
00308         interference += iIntra;
00309 
00310         assure(interference > 0.0, "Interference is not positive!");
00311         assure(signal > 0.0, "Carrier Signal is not greater than zero!");
00312 
00313         //return value
00314         wns::CandI candi = wns::CandI();
00315         candi.sdma.iIntra = wns::Power::from_mW(iIntra);
00316         candi.C = wns::Power::from_mW(signal);
00317         candi.I = wns::Power::from_mW(interference);
00318         candis[*s] = candi;
00319     }
00320     return candis;
00321 }
00322 
00323 double
00324 Beamforming::estimateDoA(Station* id)
00325 {
00326     double azi = (id->getPosition() - this->getStation()->getPosition()).getAzimuth();
00327     azi += dis() * M_PI/180;
00328     return( azi );
00329 }
00330 
00331 
00332 PatternPtr
00333 Beamforming::calculateAndSetBeam(Station* id,
00334                                  const std::vector<Station*>& undesired,
00335                                  wns::Power omniPower)
00336 {
00337     PatternPtr beam = p_calculateBeam(id, undesired, omniPower);
00338     return beam;
00339 }
00340 
00341 double
00342 Beamforming::calculatePhaseDelta(int antennaNo, double stationPhi) const
00343 {
00344     // stationPhi in radians
00345     double delta = 0.0;
00346     double alpha = 0.0;
00347     // antenna spacing: lambda/2 = pi
00348     double antennaSpacing = M_PI;
00349     // radius of array is adapted to the antennaSpacing
00350     double r = antennaSpacing/2 / sin(M_PI / double(pd_noAntennaElements));
00351 
00352     switch (arrayLayout)
00353     {
00354     case circular:
00355         // antenna elements are assumed to be on a circle with (x=0, y=0) as
00356         // center, first element is located at (x=r, y=0)
00357         alpha = double(antennaNo) * 2.0 * M_PI / double(pd_noAntennaElements);
00358         delta = r*sqrt(2.0-2.0*cos(alpha))*sin(-stationPhi-alpha/2.0);
00359 
00360         break;
00361     case linear:
00362     default: // Linear is default
00363         // elements are assumed to be lined up along the y-axis, first antenna
00364         // element located at (x=0, y=0)
00365         delta = double(antennaNo)*antennaSpacing*sin(stationPhi);
00366     }
00367 
00368     return delta;
00369 }
00370 
00371 
00372 PatternPtr
00373 Beamforming::p_calculateBeam(Station* id,
00374                              const std::vector<Station*>& undesired,
00375                              wns::Power omniPower)
00376 {
00377     // assure that the cov matrix, which is inverted later, has
00378     // non-zero diagonal-elements. Otherwise the algorithms performes unpredictable
00379     assure(omniPower.get_mW() > 0, "beam pattern calculation requires positive level of omni-directional power");
00380 
00381     std::complex<double> c;
00382     boost::numeric::ublas::vector<std::complex<double> > steervector(pd_noAntennaElements); 
00383     boost::numeric::ublas::matrix<std::complex<double> > kov(pd_noAntennaElements, pd_noAntennaElements);
00384     kov = 
00385         boost::numeric::ublas::zero_matrix<std::complex<double> >(pd_noAntennaElements, pd_noAntennaElements);
00386 
00387     assure(getStation() != id, "Desired and beamforming station are the same!");
00388     //build covariance matrix:
00389     wns::Position myPosition = getPosition();
00390     for (std::vector<Station*>::const_iterator s = undesired.begin(); s != undesired.end(); s ++){
00391         //build steering vector:
00392         assure(*s != getStation(), "Undesired and beamforming station are the same!");
00393         assure(*s != id, "Undesired and desired station are the same!");
00394 
00395         pd_azimuthAngles [*s] = ((*s)->getAntenna()->getPosition() - myPosition).getAzimuth();
00396         //add positionError to azimuth calculation (in order to model the actual position estimation)
00397         pd_azimuthAngles [*s] += dis() * M_PI/180;
00398 
00399         if (pd_azimuthAngles[*s] < 0)
00400             pd_azimuthAngles[*s] += M_PI + M_PI;
00401 
00402         for (unsigned long int i = 0; i < pd_noAntennaElements; i++)
00403         {
00404             c = std::polar(1.0, calculatePhaseDelta(i, pd_azimuthAngles[*s]));
00405             steervector(i) = c;
00406         }
00407         assure(pd_lastPowerReceived.find(*s) != pd_lastPowerReceived.end(), "Station is not yet registered at this antenna!");
00408         //Hermitian rank 1 update
00409         kov += pd_lastPowerReceived[*s].get_mW() 
00410             * boost::numeric::ublas::outer_prod(steervector, boost::numeric::ublas::conj(steervector));
00411     }
00412 
00413     //desired station as last, is also needed for weight calculation
00414     pd_azimuthAngles [id] = (id->getAntenna()->getPosition() - myPosition).getAzimuth();
00415     //add positionError to azimuth calculation (in order to model the actual position estimation)
00416     pd_azimuthAngles [id] += dis() * M_PI/180;
00417 
00418     if (pd_azimuthAngles[id] < 0)
00419         pd_azimuthAngles[id] += M_PI + M_PI;
00420     for (unsigned long int i = 0; i < pd_noAntennaElements; i++)
00421     {
00422         c = std::polar(1.0, calculatePhaseDelta(i, pd_azimuthAngles[id]));
00423         steervector(i) = c;
00424     }
00425     assure(pd_lastPowerReceived.find(id) != pd_lastPowerReceived.end(), "Station is not yet registered at this antenna!");
00426     //Hermitian rank 1 update
00427     kov += pd_lastPowerReceived[id].get_mW()
00428          * boost::numeric::ublas::outer_prod(steervector, boost::numeric::ublas::conj(steervector));
00429 
00430    //covariance matrix almost complete, now only noise entries necessary:
00431     std::complex<double> n = std::complex<double>(omniPower.get_mW(), 0);
00432     for (unsigned long int i = 0; i < pd_noAntennaElements; i++){
00433         kov(i, i) = kov(i, i) + n;
00434     }
00435     //Calculate Weight vector
00436     boost::numeric::ublas::vector<std::complex<double> > w(pd_noAntennaElements);
00437     // restore full matrix:
00438     p_herm_rest(kov, pd_noAntennaElements);
00439     //Solving kov*w = sttervector using LU method:
00440     boost::numeric::ublas::permutation_matrix<> p(pd_noAntennaElements);
00441     boost::numeric::ublas::lu_factorize(kov, p);
00442     w = steervector;
00443     boost::numeric::ublas::lu_substitute(kov, p, w);
00444 
00445     // compute antenna pattern:
00446     std::complex<double> pattern[360];
00447     boost::numeric::ublas::vector<std::complex<double> > wTrans = boost::numeric::ublas::trans(w);
00448     for (unsigned long int i = 0; i < 360; i++){
00449         pattern[i] = boost::numeric::ublas::inner_prod(wTrans, (*steervectors[i]));
00450     }
00451     //Normalize pattern to transmit / receive the same power as an omni-antenna:
00452     double sumPower = 0.0;
00453     for (unsigned long int i = 0; i < 360; i++)
00454         sumPower += pow(std::abs(pattern[i]),2);
00455     sumPower = sumPower / 360;
00456 
00457     PatternPtr beam(new Pattern());
00458     beam->pattern.reserve(360);
00459     for (unsigned long int i = 0; i < 360; i++)
00460     {
00461         double amplitudeFactor = std::abs(pattern[i])/sqrt(sumPower);
00462         beam->pattern.push_back(amplitudeFactor);
00463     }
00464     assure(beam->getSize() == 360, "pattern has no valid size");
00465     // the omni attenuation factor is no longer needed, it is always one
00466     //beam->omniAttenuation = wns::Ratio::from_factor(1);
00467     unsigned long int grad = (unsigned long int)(pd_azimuthAngles[id]*180/M_PI +0.5); //0.5 to round
00468     if(grad == 360) grad = 0;
00469     assure(grad < beam->pattern.size(), "pattern index (grad) out of range");
00470     double desiredAntennaFactor =  beam->pattern.at(grad);
00471 
00472     MESSAGE_BEGIN(VERBOSE, log, m, "");
00473     m << "antenna factor in look direction: "<< desiredAntennaFactor << "\n";
00474     m << "antenna factor(s) to undesired station(s): ";
00475     for (std::vector<Station*>::const_iterator s = undesired.begin(); s != undesired.end(); s ++){
00476         grad = (unsigned long int)(pd_azimuthAngles[*s]*180/M_PI +0.5); //0.5 to round
00477         if(grad == 360) grad = 0;
00478         m << beam->pattern.at(grad) << " ";
00479     }
00480     MESSAGE_END();
00481 
00482     for (std::vector<Station*>::const_iterator s = undesired.begin(); s != undesired.end(); s ++){
00483         grad = (unsigned long int)(pd_azimuthAngles[*s]*180/M_PI +0.5); //0.5 to round
00484         if(grad == 360) grad = 0;
00485 
00486         if( beam->pattern.at(grad) > desiredAntennaFactor){
00487             MESSAGE_BEGIN(NORMAL, log, m, "");
00488             m << "antenna factor in look direction: "<< desiredAntennaFactor
00489               << " is smaller than antenna factor to undesired station "
00490               << beam->pattern.at(grad);
00491             MESSAGE_END();
00492             drawRadiationPattern();
00493         }
00494     }
00495     return beam;
00496 }
00497 
00498 
00499 void Beamforming::p_herm_rest(boost::numeric::ublas::matrix<std::complex<double> >& c, const unsigned long int m) const
00500 {
00501     //Restoration of efficiently stored hermitian matrix
00502     std::complex<double> z;
00503     double re, im;
00504     for (unsigned long int i = 0; i < m; i++){
00505         for (unsigned long int j = i+1; j < m; j++){
00506             re = c(i, j).real();
00507             im = c(i, j).imag();
00508             z = std::complex<double>(re, -im);
00509             c(j, i) = z;
00510             // real part symmetrically completed, imaginary part neg. symm.
00511         }
00512     }
00513 }
00514 
00515 void Beamforming::drawRadiationPattern(std::string file, PatternPtr pattern)
00516 {
00517     const unsigned long int resolution = 360;
00518     double step = 2 * M_PI / resolution;
00519     //double zero_dB_length = radius;
00520     double length = 0, angle = 0;
00521     wns::Ratio gain = wns::Ratio::from_dB(0),
00522         gain_min = wns::Ratio::from_dB(-10);
00523     std::fstream outfile;
00524     outfile.open(file.c_str(), std::ios::out | std::ios::app);
00525     if (!outfile.is_open())
00526     {
00527         MESSAGE_BEGIN(NORMAL, log, m,"File ");
00528         m << file + " could not be opened." + " Simulation will continue.\n";
00529         MESSAGE_END();
00530         return;
00531     }
00532     wns::Position myPosition = getPosition();
00533     for (unsigned long int k=0; k<resolution; k++)
00534     {
00535         angle = step * k;
00536         gain = pd_getGainEntry(k, pattern);
00537 //      if (gain<gain_min) length = 0;
00538 //      else length = (zero_dB_length /(-gain_min.get_dB())) * gain.get_dB() + zero_dB_length;
00539         length = gain.get_factor();
00540         outfile << myPosition.getX() + length * cos(angle) <<  " "
00541                 << myPosition.getY() + length * sin(angle) << std::endl;
00542     }
00543     outfile << "\n";
00544     outfile.close();
00545 }
00546 
00547 void Beamforming::drawRadiationPattern() const
00548 {
00549     const unsigned long int resolution = 360;
00550     double step = 2 * M_PI / resolution, length = radius, angle = 0;
00551     std::fstream outfile;
00552     outfile.open(patternOutputFile.c_str(), std::ios::out | std::ios::app);
00553     if (!outfile.is_open())
00554     {
00555         MESSAGE_BEGIN(NORMAL, log, m,"File ");
00556         m << patternOutputFile + " could not be opened." + " Simulation will continue.\n";
00557         MESSAGE_END();
00558         return;
00559     }
00560     wns::Position myPosition = getPosition();
00561     for (unsigned long int k=0; k<resolution; k++)
00562     {
00563         angle = step * k;
00564         outfile << myPosition.getX() + length * cos(angle) <<  " "
00565                 << myPosition.getY() + length * sin(angle) << std::endl;
00566     }
00567     outfile << "\n";
00568     outfile.close();
00569 }
00570 
00571 

Generated on Mon May 21 03:31:59 2012 for openWNS by  doxygen 1.5.5