JakesFading.cc

00001 //
00002 // This program is free software: you can redistribute it and/or modify
00003 // it under the terms of the GNU Lesser General Public License as published by
00004 // the Free Software Foundation, either version 3 of the License, or
00005 // (at your option) any later version.
00006 //
00007 // This program is distributed in the hope that it will be useful,
00008 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 // GNU Lesser General Public License for more details.
00011 //
00012 // You should have received a copy of the GNU Lesser General Public License
00013 // along with this program.  If not, see http://www.gnu.org/licenses/.
00014 //
00015 
00016 #include "JakesFading.h"
00017 #include <BaseWorldUtility.h>
00018 
00019 DimensionSet JakesFadingMapping::dimensions(Dimension::time_static());
00020 
00021 double JakesFadingMapping::getValue(const Argument& pos) const {
00022   double f = model->carrierFrequency;
00023   double v = relSpeed;
00024   simtime_t t = pos.getTime();
00025   double re_h = 0;
00026   double im_h = 0;
00027 
00028   // Compute Doppler shift.
00029   double doppler_shift = v * f / BaseWorldUtility::speedOfLight;
00030 
00031   for (int i = 0; i < model->fadingPaths; i++) {
00032     // Some math for complex numbers:
00033     //
00034     // Cartesian form: z = a + ib
00035     // Polar form:     z = p * e^i(phi)
00036     //
00037     // a = p * cos(phi)
00038     // b = p * sin(phi)
00039     // z1 * z2 = p1 * p2 * e^i(phi1 + phi2)
00040 
00041     // Phase shift due to Doppler => t-selectivity.
00042     double phi_d = model->angleOfArrival[i] * doppler_shift;
00043     // Phase shift due to delay spread => f-selectivity.
00044     double phi_i = model->delay[i].dbl() * f;
00045     // Calculate resulting phase due to t-selective and f-selective fading.
00046     double phi = 2.00 * M_PI * (phi_d * t.dbl() - phi_i);
00047 
00048     // One ring model/Clarke's model plus f-selectivity according to Cavers:
00049     // Due to isotropic antenna gain pattern on all paths only a^2 can be received on all paths.
00050     // Since we are interested in attenuation a:=1, attenuation per path is then:
00051     double attenuation = (1.00 / sqrt(static_cast<double>(model->fadingPaths)));
00052 
00053     // Convert to cartesian form and aggregate {Re, Im} over all fading paths.
00054     re_h = re_h + attenuation * cos(phi);
00055     im_h = im_h - attenuation * sin(phi);
00056   }
00057 
00058   // Output: |H_f|^2 = absolute channel impulse response due to fading.
00059   // Note that this may be >1 due to constructive interference.
00060   return re_h * re_h + im_h * im_h;
00061 }
00062 
00063 
00064 JakesFading::JakesFading(int fadingPaths, simtime_t delayRMS,
00065              Move* hostMove, double carrierFrequency,
00066              simtime_t interval):
00067   fadingPaths(fadingPaths),
00068   hostMove(hostMove),
00069   carrierFrequency(carrierFrequency),
00070   interval(interval)
00071 {
00072   angleOfArrival = new double[fadingPaths];
00073   delay = new simtime_t[fadingPaths];
00074 
00075   for (int i = 0; i < fadingPaths; i++) {
00076     angleOfArrival[i] = cos(uniform(0, M_PI));
00077     delay[i] = exponential(delayRMS);
00078   }
00079 }
00080 
00081 JakesFading::~JakesFading() {
00082   delete[] delay;
00083   delete[] angleOfArrival;
00084 }
00085 
00086 void JakesFading::filterSignal(Signal& s)
00087 {
00088   const Move& senderMove = s.getMove();
00089   double relSpeed = (senderMove.getDirection() * senderMove.getSpeed()
00090              - hostMove->getDirection() * hostMove->getSpeed()).length();
00091 
00092   simtime_t start = s.getSignalStart();
00093   simtime_t end = start + s.getSignalLength();
00094 
00095   s.addAttenuation(new JakesFadingMapping(this, relSpeed,
00096                       Argument(start),
00097                       interval,
00098                       Argument(end)));
00099 }