![]() |
User Manual, Developers Guide and API Documentation |
![]() |
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
1.5.5