User Manual, Developers Guide and API Documentation

Brown.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/scenario/mobility/Brown.hpp>
00029 #include <WNS/module/Base.hpp>
00030 #include <WNS/distribution/Distribution.hpp>
00031 #include <fstream>
00032 #include <iostream>
00033 
00034 using namespace rise;
00035 using namespace rise::scenario::mobility;
00036 using namespace std;
00037 
00038 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00039     BrownianRect,
00040     MobilityInterface,
00041     "rise.mobility.BrownianRect",
00042     wns::PyConfigViewCreator);
00043 
00044 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00045     BrownianCirc,
00046     MobilityInterface,
00047     "rise.mobility.BrownianCirc",
00048     wns::PyConfigViewCreator);
00049 
00050 STATIC_FACTORY_REGISTER_WITH_CREATOR(
00051     BrownianEquiangularPolygon,
00052     MobilityInterface,
00053     "rise.mobility.BrownianEquiangularPolygon",
00054     wns::PyConfigViewCreator);
00055 
00056 BrownianBase::BrownianBase(const wns::pyconfig::View& mobilityView) :
00057     Mobility(mobilityView),
00058     velocityVector()
00059 {
00060     initRNGs();
00061 
00062     wns::rng::RNGen* rng = 
00063         wns::simulator::getRegistry()->find<wns::rng::RNGen*>("MOBILITY-RNG");
00064 
00065     wns::pyconfig::View velocityConfig(mobilityView, "userVelocityDist");
00066 
00067     std::string name = velocityConfig.get<std::string>("__plugin__");
00068     velocityDistribution =
00069         wns::distribution::RNGDistributionFactory::creator(name)->create(rng, velocityConfig);
00070 
00076     velocityVector.setPolar((*velocityDistribution)() * moveTimeStep,
00077                 (*angleDistribution)(),
00078                 M_PI/2.0); 
00079     velocityVector.setDeltaZ(0.0);
00080 
00081     fetchObstructionList(mobilityView);
00082 
00083     MESSAGE_BEGIN(NORMAL, log, m, "Mobility Object created at ");
00084     m << getPosition() << " with velocity "
00085       << velocityVector.getR()/moveTimeStep
00086       << " m/s and direction " << velocityVector.getAzimuth()
00087       << " considering " << obstructionList.size() << " obstructions.";
00088     MESSAGE_END();
00089 
00090     // trigger the periodic mobility updates
00091     startPeriodicTimeout(moveTimeStep, moveTimeStep);
00092 }
00093 
00094 void
00095 BrownianBase::initRNGs()
00096 {
00097     wns::rng::RNGen* rng = wns::simulator::getRegistry()->find<wns::rng::RNGen*>("MOBILITY-RNG");
00098 
00099     angleDistribution = new wns::distribution::Uniform(0.0, 2.0 * M_PI, rng);
00100     updateProbability = new wns::distribution::StandardUniform(rng);
00101     
00102 }
00103 
00104 BrownianBase::~BrownianBase()
00105 {
00106     delete velocityDistribution;
00107     delete angleDistribution;
00108     delete updateProbability;
00109 }
00110 
00111 void
00112 BrownianBase::newVelocityVector()
00113 {
00114     // some abbreviations
00115     double myVelocity = velocityVector.getR()/moveTimeStep;
00116     double aVelocity = 0.0;
00117 
00118     // draw new direction
00119     velocityVector.setAzimuth((*angleDistribution)());
00120 
00121     // draw new velocity
00122     do
00123     {
00124         aVelocity = (myVelocity + (*velocityDistribution)()) / 2;
00125     } while (aVelocity <= 0.0);
00126 
00127     velocityVector.setR(aVelocity*moveTimeStep);
00128 
00129     MESSAGE_BEGIN(NORMAL, log, m, "Changed Velocity and Direction: ");
00130     m << " Velocity: " << velocityVector.getR()/moveTimeStep
00131         << " Direction: " << velocityVector.getAzimuth();
00132     MESSAGE_END();
00133 }
00134 
00135 void
00136 BrownianBase::move()
00137 {
00138     // velocity-dependent random experiment for direction update
00139     if ((*updateProbability)()*moveTimeStep<0.0004*velocityVector.getR())
00140         newVelocityVector();
00141 
00142     // update position
00143     wns::Position newPosition = getPosition() + velocityVector;
00144     
00145     MESSAGE_BEGIN(NORMAL, log, m, "New Position?: ");
00146     m << "Old Position: " << getPosition()
00147     << "New Position: " << newPosition;
00148     MESSAGE_END();
00149     
00150     while(!checkBounds(newPosition))
00151     {
00152         if ((*updateProbability)()*moveTimeStep<0.0004*velocityVector.getR())
00153             newVelocityVector();
00154         
00155         newPosition = getPosition() + velocityVector;
00156         
00157         MESSAGE_BEGIN(NORMAL, log, m, "New Position?: ");
00158         m << "Old Position: " << getPosition()
00159         << "New Position: " << newPosition;
00160         MESSAGE_END();
00161     }
00162     
00163     // check if bounds are exceeded
00164 //  if ( !checkBounds(newPosition) ){
00165 //      // turn 180 degrees
00166 //      velocityVector.setAzimuth( velocityVector.getAzimuth() + M_PI );
00167 //      newPosition = getPosition() + velocityVector;
00168 //      assure( checkBounds(newPosition), "Oops. Can't go back where I came from!");
00169 //      //continue;
00170 //  }
00171     
00172     // bounds check ok, set new position
00173     setPosition(newPosition);
00174     
00175     fstream fileout;
00176     fileout.open("mobilityStationPositions", ios::out | ios::app);
00177     fileout << getPosition() << endl;
00178     fileout.close();
00179 
00180     MESSAGE_BEGIN(NORMAL, log, m, "Mobility update: ");
00181     m << "Position: " << getPosition()
00182       << " Velocity: " << velocityVector.getR()/moveTimeStep
00183       << " Distance: " << velocityVector.getR()
00184       << " Direction: " << velocityVector.getAzimuth();
00185     MESSAGE_END();
00186 }
00187 
00188 void
00189 BrownianBase::periodically()
00190 {
00191     move();
00192 }
00193 
00194 void
00195 BrownianBase::fetchObstructionList(const wns::pyconfig::View& config)
00196 {
00197     obstructionList.clear();
00198 
00199     for( int ii = 0; ii < config.len("obstructionList"); ++ii)
00200     {
00201         wns::pyconfig::View objectView = config.getView("obstructionList", ii);
00202 
00203         // ToDo: Implement static factory similar to rise::scenario::shadowing::Object.hpp
00204         assure(objectView.get<std::string>("__plugin__") == "rise.shadowing.obstruction.AxisParallelRectangle",
00205                "Only AxisParallelRectangle is supported as object");
00206 
00207         wns::geometry::Point a(objectView.getView("pointA"));
00208         wns::geometry::Point b(objectView.getView("pointB"));
00209         obstructionList.push_front(wns::geometry::AxisParallelRectangle(a,b));
00210     }
00211 }
00212 
00214 bool
00215 BrownianBase::isObstructed(const wns::Position& pos) const
00216 {
00217     for (std::list<wns::geometry::AxisParallelRectangle>::const_iterator iter = obstructionList.begin();
00218          iter != obstructionList.end();
00219          ++iter)
00220     {
00221         if ((*iter).contains(pos)){
00222             // found one match --> the point is obstructed
00223             return true;
00224         }
00225     }
00226     // no match occured
00227     return false;
00228 }
00229 
00230 BrownianRect::BrownianRect(const wns::pyconfig::View& mobilityView)
00231     : BrownianBase(mobilityView),
00232       xmin(mobilityView.get<double>("xmin")),
00233       ymin(mobilityView.get<double>("ymin")),
00234       xmax(mobilityView.get<double>("xmax")),
00235       ymax(mobilityView.get<double>("ymax"))
00236 {}
00237 
00238 bool
00239 BrownianRect::checkBounds(const wns::Position& pos) const
00240 {
00241     // range check
00242     if ( (pos.getX() <= xmin) || (pos.getX() >= xmax) ) return false;
00243     if ( (pos.getY() <= ymin) || (pos.getY() >= ymax) ) return false;
00244     return !BrownianBase::isObstructed(pos);
00245 }
00246 
00247 BrownianCirc::BrownianCirc(const wns::pyconfig::View& mobilityView) :
00248     BrownianBase(mobilityView),
00249     center(mobilityView.getView("center")),
00250     maxDistance(mobilityView.get<double>("maxDistance")),
00251     nSectors(mobilityView.get<int>("nSectors"))
00252 {}
00253 
00254 bool
00255 BrownianCirc::checkBounds(const wns::Position& pos) const
00256 {
00257     // range check
00258     MESSAGE_BEGIN(NORMAL, log, m, "Check Bounds: ");
00259     m << "Angle: " << (pos-center).getAzimuth()
00260     << " Center: " << center
00261     << " SS position: " << pos 
00262     << " Distance: " << (center-pos).getR();
00263     MESSAGE_END();
00264     
00265     wns::Position posWithZ;
00266     
00267     posWithZ.setX(pos.getX());
00268     posWithZ.setY(pos.getY());
00269     posWithZ.setZ(center.getZ());
00270 
00271     MESSAGE_BEGIN(NORMAL, log, m, "Check Bounds: ");
00272     m << "Angle: " << (posWithZ-center).getAzimuth()
00273             << " Center: " << center
00274             << " SS position: " << posWithZ 
00275             << " Distance: " << (center-posWithZ).getR();
00276     MESSAGE_END();
00277     
00278     if(nSectors > 1)
00279     {
00280         if ( (center-posWithZ).getR() >= maxDistance || (posWithZ-center).getAzimuth() > M_PI/2 || (posWithZ-center).getAzimuth() < ((M_PI/2) - (2*M_PI/nSectors)) ) 
00281         {
00282             return false;
00283         }
00284     }
00285     else
00286     {
00287         if ( (center-posWithZ).getR() >= maxDistance ) 
00288         {
00289             return false;
00290         }
00291     }
00292     
00293     return !BrownianBase::isObstructed(pos);
00294 }
00295 
00296 
00297 BrownianEquiangularPolygon::BrownianEquiangularPolygon(const wns::pyconfig::View& mobilityView) :
00298     BrownianBase(mobilityView),
00299     center(mobilityView.getView("center")),
00300     maxDistance(mobilityView.get<double>("maxDistance")),
00301     corners(mobilityView.get<int>("corners")),
00302     angle(mobilityView.get<double>("angle"))
00303 {}
00304 
00305 bool
00306 BrownianEquiangularPolygon::checkBounds(const wns::Position& pos) const
00307 {
00308     const wns::Position& c = center;
00309     const wns::Position& d = pos;
00310     double ao = angle*2*M_PI/360;
00311     for (int ii=0;ii<corners;++ii)
00312     {
00313         wns::Position a = c+wns::PositionOffset(maxDistance*cos(ao+ ii   *M_PI*2/corners),maxDistance*sin(ao+ ii   *M_PI*2/corners),0);
00314         wns::Position b = c+wns::PositionOffset(maxDistance*cos(ao+(ii+1)*M_PI*2/corners),maxDistance*sin(ao+(ii+1)*M_PI*2/corners),0);
00315         // are lines parallel?
00316         double rd = (b.getX()-a.getX())*(d.getY()-c.getY()) - (b.getY()-a.getY())*(d.getX()-c.getX()); 
00317         if (rd==0) continue;
00318         // find intersection
00319         double rn = (a.getY()-c.getY())*(d.getX()-c.getX()) - (a.getX()-c.getX())*(d.getY()-c.getY());
00320         double sn = (a.getY()-c.getY())*(b.getX()-a.getX()) - (a.getX()-c.getX())*(b.getY()-a.getY());
00321         double intersection_ab = rn / rd;
00322         double intersection_cd = sn / rd;
00323         if (!(intersection_ab<0 or intersection_ab>1 or intersection_cd<0 or intersection_cd>1)) return false;
00324     }
00325     return !BrownianBase::isObstructed(pos);
00326 }
00327 
00328 
00329 

Generated on Mon May 21 03:32:00 2012 for openWNS by  doxygen 1.5.5