User Manual, Developers Guide and API Documentation

CorrelatedStaticZF.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 <OFDMAPHY/receiver/mimo/CorrelatedStaticZF.hpp>
00029 #include <OFDMAPHY/receiver/Receiver.hpp>
00030 
00031 #include <WNS/geometry/Vector.hpp>
00032 
00033 #include <boost/numeric/ublas/io.hpp>
00034 #include <boost/numeric/ublas/vector.hpp>
00035 #include <boost/numeric/ublas/vector_proxy.hpp>
00036 #include <boost/numeric/ublas/triangular.hpp>
00037 #include <boost/numeric/ublas/lu.hpp>
00038 
00039 #include <math.h>
00040 
00041 using namespace ofdmaphy::receiver::mimo;
00042 
00043 STATIC_FACTORY_REGISTER_WITH_CREATOR(CorrelatedStaticZF,
00044                                      ICalculationStrategy,
00045                                      "CorrelatedStaticZF",
00046                                      ICalculationStrategyCreator);
00047 
00048 CorrelatedStaticZF::CorrelatedStaticZF(const wns::pyconfig::View& _config,
00049                                        Receiver* _rx,
00050                                        wns::logger::Logger* _logger):
00051     ICalculationStrategy(_config, _rx, _logger),
00052     logger(_logger),
00053     rx(_rx),
00054     arrayOrientation(_config.get<double>("arrayOrientation")),
00055     antennaSpacing(_config.get<double>("antennaSpacing")),
00056     angleSpread(_config.get<double>("angleSpread"))
00057 {
00058     assure(arrayOrientation >= 0.0, "Antenna angle cannot be negative");
00059     assure(arrayOrientation <= M_PI, "Anntenna angle cannot exceed PI");
00060 }
00061 
00062 std::vector<wns::Ratio>
00063 CorrelatedStaticZF::getPostProcessingSINRFactor(rise::TransmissionObjectPtr t)
00064 {
00065     // number of spatial streams and rx antennas
00066     int n_SS = t->getNumberOfSpatialStreams();
00067     int n_RX = rx->getOFDMAStation()->getNumAntennas();
00068 
00069     if(n_SS > n_RX)
00070     {
00071         // More streams than receive antennas -> no usefull reception possible
00072         return std::vector<wns::Ratio>(n_SS, wns::Ratio::from_factor(1e-12));
00073     }
00074 
00075     // this is the MIMO Gain without any correlation
00076     wns::Ratio noCorrelationGain = wns::Ratio::from_factor(double(n_RX - n_SS + 1)/double(n_SS));
00077     MESSAGE_SINGLE(NORMAL, *logger, "CorrelatedStaticZF: Gain w/o correlation: " << noCorrelationGain);
00078 
00079     // get the transmitting station
00080     ofdmaphy::Station* txStation = dynamic_cast<ofdmaphy::Station*>(t->getTransmitter()->getStation());
00081     assure(txStation, "Peer is not an OFDMA station");
00082 
00083     // get the peer mimo-processing routine and cast it to CorrelatedStaticZF to
00084     // read the required performance values
00085     CorrelatedStaticZF* peer = txStation->getReceiver()->getMIMOProcessing<CorrelatedStaticZF>();
00086 
00087     // calculate Angle of Departure and Angle of Arrival by creating two vectors
00088     // tx->rx and rx->tx
00089     wns::Position txPosition = txStation->getPosition();
00090     wns::Position rxPosition = rx->getStation()->getPosition();
00091 
00092     double AoD = wns::geometry::Vector(txPosition, rxPosition).getAzimuth()
00093         + peer->getArrayOrientation();
00094     if(AoD < 0)
00095     {
00096         AoD += M_PI;
00097     }
00098     else if(AoD > M_PI)
00099     {
00100         AoD -= M_PI;
00101     }
00102 
00103     double AoA = wns::geometry::Vector(rxPosition, txPosition).getAzimuth()
00104         + this->arrayOrientation;
00105     if(AoA < 0)
00106     {
00107         AoA += M_PI;
00108     }
00109     else if(AoA > M_PI)
00110     {
00111         AoA -= M_PI;
00112     }
00113 
00114     // compute loss due to tx and rx correlation
00115     std::vector<wns::Ratio> txLoss = getCorrelationLoss(n_SS, AoD, peer->getAntennaSpacing(), peer->getAngleSpread());
00116     std::vector<wns::Ratio> rxLoss = getCorrelationLoss(n_RX, AoA, this->antennaSpacing, this->getAngleSpread());
00117 
00118     MESSAGE_BEGIN(NORMAL, *logger, m, "CorrelatedStaticZF:");
00119     m << " tx pos " << txPosition;
00120     m << " rx pos " << rxPosition;
00121     MESSAGE_END();
00122 
00123     MESSAGE_BEGIN(NORMAL, *logger, m, "CorrelatedStaticZF: TX");
00124     m << " orientation " << peer->getArrayOrientation();
00125     m << " AoD " << AoD/M_PI*180 << "d";
00126     m << " ASD " << peer->getAngleSpread() << "rad";
00127     m << " spacing " << peer->getAntennaSpacing();
00128     m << " -> loss: ";
00129     for(std::vector<wns::Ratio>::const_iterator it = txLoss.begin();
00130         it != txLoss.end();
00131         ++it)
00132     {
00133         m << (*it) << " ";
00134     }
00135     MESSAGE_END();
00136 
00137     MESSAGE_BEGIN(NORMAL, *logger, m, "CorrelatedStaticZF: RX");
00138     m << " orientation " << this->getArrayOrientation();
00139     m << " AoA " << AoA/M_PI*180 << "d";
00140     m << " ASA " << this->getAngleSpread() << "rad";
00141     m << " spacing " << this->getAntennaSpacing();
00142     m << " -> loss: ";
00143     for(std::vector<wns::Ratio>::const_iterator it = rxLoss.begin();
00144         it != rxLoss.end();
00145         ++it)
00146     {
00147         m << (*it) << " ";
00148     }
00149     MESSAGE_END();
00150 
00151     // calculate result vector
00152     std::vector<wns::Ratio> r;
00153     std::vector<wns::Ratio>::iterator itTx = txLoss.begin();
00154     std::vector<wns::Ratio>::iterator itRx = rxLoss.begin();
00155 
00156     for(;
00157         itTx != txLoss.end();
00158         ++itTx, ++itRx)
00159     {
00160         r.push_back(noCorrelationGain - *itTx - *itRx);
00161     }
00162 
00163     // single antenna fallback
00164     if(r[0].get_dB() < 0 and n_SS == 1)
00165     {
00166         std::vector<wns::Ratio> rFallBack;
00167         rFallBack.push_back(wns::Ratio::from_factor(1));
00168         MESSAGE_BEGIN(NORMAL, *logger, m, "CorreltatedStaticZF: ");
00169         m << "Correlation makes MIMO impossible -> use only one rx antenna";
00170         MESSAGE_END();
00171         return rFallBack;
00172     }
00173 
00174     return r;
00175 }
00176 
00177 std::vector<wns::Ratio>
00178 CorrelatedStaticZF::getCorrelationLoss(int n, double angle, double spacing, double spread)
00179 {
00180     using namespace boost::numeric::ublas;
00181 
00182     // Compute the correlation matrix m
00183     matrix< std::complex<double> > m(n,n);
00184     std::complex<double> j(0, 1.0);
00185 
00186     for(double p = 0; p < n; ++p)
00187     {
00188         for(double q = 0; q < n; ++q)
00189         {
00190             if(p==q)
00191             {
00192                 m(p,q) = 1.0;
00193             }
00194             else
00195             {
00196                 m(p,q) = std::exp(-1.0*j*2.0*M_PI*(p-q)*spacing*cos(angle)) * std::exp(-0.5*std::pow(2.0*M_PI*(q-p)*spacing*sin(angle)*spread, 2.0));
00197             }
00198         }
00199     }
00200 
00201     // Compute the inverse of m using LU-factorization
00202     matrix< std::complex<double> > m_inv(n,n);
00203 
00204     // create a permutation matrix for the LU-factorization
00205     permutation_matrix<std::size_t> pm(m.size1());
00206     int res = lu_factorize(m, pm);
00207     if(res != 0)
00208     {
00209         // factorization not possible
00210         return(std::vector<wns::Ratio>(n, wns::Ratio::from_factor(1e10)));
00211     }
00212 
00213     // create identity matrix of "inverse"
00214     m_inv.assign(identity_matrix< std::complex<double> >(m.size1()));
00215 
00216     // backsubstitute to get the inverse
00217     lu_substitute(m, pm, m_inv);
00218 
00219     std::vector<wns::Ratio> r;
00220 
00221     for(int i = 0; i< n; ++i)
00222     {
00223         assure(m_inv(i,i).imag() < 1e-3,
00224                "Complex value at position " << i << " has imag-part of " << m_inv(i,i).imag());
00225         r.push_back(wns::Ratio::from_factor(m_inv(i,i).real()));
00226     }
00227     return r;
00228 }

Generated on Tue May 22 03:32:15 2012 for openWNS by  doxygen 1.5.5