INET Framework for OMNeT++/OMNEST
BasicMobility.cc
Go to the documentation of this file.
00001 /* -*- mode:c++ -*- ********************************************************
00002  * file:        BasicMobility.cc
00003  *
00004  * author:      Daniel Willkomm, Andras Varga
00005  *
00006  * copyright:   (C) 2004 Telecommunication Networks Group (TKN) at
00007  *              Technische Universitaet Berlin, Germany.
00008  *
00009  *              (C) 2005 Andras Varga
00010  *
00011  *              This program is free software; you can redistribute it
00012  *              and/or modify it under the terms of the GNU General Public
00013  *              License as published by the Free Software Foundation; either
00014  *              version 2 of the License, or (at your option) any later
00015  *              version.
00016  *              For further information see file COPYING
00017  *              in the top level directory
00018  ***************************************************************************
00019  * part of:     framework implementation developed by tkn
00020  **************************************************************************/
00021 
00022 
00023 #include "BasicMobility.h"
00024 #include "FWMath.h"
00025 
00026 
00027 #define coreEV (ev.isDisabled()||!coreDebug) ? (std::ostream&)ev : EV << logName() << "::BasicMobility: "
00028 
00029 static int parseInt(const char *s, int defaultValue)
00030 {
00031     if (!s || !*s)
00032         return defaultValue;
00033     char *endptr;
00034     int value = strtol(s, &endptr, 10);
00035     return *endptr=='\0' ? value : defaultValue;
00036 }
00037 
00038 
00039 void BasicMobility::initialize(int stage)
00040 {
00041     BasicModule::initialize(stage);
00042 
00043     EV << "initializing BasicMobility stage " << stage << endl;
00044 
00045     if (stage == 0)
00046     {
00047         cc = ChannelControl::get();
00048 
00049         // get a pointer to the host
00050         hostPtr = findHost();
00051         myHostRef = cc->registerHost(hostPtr, Coord());
00052     }
00053     else if (stage == 1)
00054     {
00055         // playground size gets set up by ChannelControl in stage==0 (Andras)
00056         // read the playgroundsize from ChannelControl
00057         Coord pgs = cc->getPgs();
00058 
00059         // reading the coordinates from omnetpp.ini makes predefined scenarios a lot easier
00060         // -1 indicates start at display string position, or random position if it's not present
00061         pos.x = pos.y = -1;
00062         if (hasPar("x"))   // not all mobility models have an "x" parameter
00063             pos.x = par("x");
00064         if (pos.x == -1)
00065             pos.x = parseInt(hostPtr->getDisplayString().getTagArg("p",0), -1);
00066         if (pos.x == -1)
00067             pos.x = uniform(0, pgs.x);
00068 
00069         if (hasPar("y")) // not all mobility models have an "y" parameter
00070             pos.y = par("y");
00071         if (pos.y == -1)
00072             pos.y = parseInt(hostPtr->getDisplayString().getTagArg("p",1), -1);
00073         if (pos.y == -1)
00074             pos.y = uniform(0, pgs.y);
00075 
00076         // check validity of position
00077         if (pos.x < 0 || pos.y < 0 || pos.x >= pgs.x || pos.y >= pgs.y)
00078             error("node position (%d,%d) is outside the playground", pos.x, pos.y);
00079 
00080         // adjusting the display string is no longer needed (Andras)
00081 
00082         // print new host position on the screen and update bb info
00083         updatePosition();
00084     }
00085 }
00086 
00087 void BasicMobility::handleMessage(cMessage * msg)
00088 {
00089     if (!msg->isSelfMessage())
00090         error("mobility modules can only receive self messages");
00091 
00092     handleSelfMsg(msg);
00093 }
00094 
00095 
00096 void BasicMobility::updatePosition()
00097 {
00098     cc->updateHostPosition(myHostRef, pos);
00099 
00100     if (ev.isGUI())
00101     {
00102         double r = cc->getCommunicationRange(myHostRef);
00103         hostPtr->getDisplayString().setTagArg("p", 0, (long) pos.x);
00104         hostPtr->getDisplayString().setTagArg("p", 1, (long) pos.y);
00105         hostPtr->getDisplayString().setTagArg("r", 0, (long) r);
00106     }
00107     nb->fireChangeNotification(NF_HOSTPOSITION_UPDATED, &pos);
00108 }
00109 
00110 
00115 Coord BasicMobility::getRandomPosition()
00116 {
00117     Coord p;
00118     p.x = uniform(0, cc->getPgs()->x);
00119     p.y = uniform(0, cc->getPgs()->y);
00120     return p;
00121 }
00122 
00123 void BasicMobility::reflectIfOutside(Coord& targetPos, Coord& step, double& angle)
00124 {
00125     if (pos.x < 0)
00126     {
00127         pos.x = -pos.x;
00128         targetPos.x = -targetPos.x;
00129         step.x = -step.x;
00130         angle = 180 - angle;
00131     }
00132     else if (pos.x >= getPlaygroundSizeX())
00133     {
00134         pos.x = 2*getPlaygroundSizeX() - pos.x;
00135         targetPos.x = 2*getPlaygroundSizeX() - targetPos.x;
00136         step.x = -step.x;
00137         angle = 180 - angle;
00138     }
00139     if (pos.y < 0)
00140     {
00141         pos.y = -pos.y;
00142         targetPos.y = -targetPos.y;
00143         step.y = -step.y;
00144         angle = -angle;
00145     }
00146     else if (pos.y >= getPlaygroundSizeY())
00147     {
00148         pos.y = 2*getPlaygroundSizeY() - pos.y;
00149         targetPos.y = 2*getPlaygroundSizeY() - targetPos.y;
00150         step.y = -step.y;
00151         angle = -angle;
00152     }
00153 }
00154 
00155 void BasicMobility::wrapIfOutside(Coord& targetPos)
00156 {
00157     if (pos.x < 0)
00158     {
00159         pos.x += getPlaygroundSizeX();
00160         targetPos.x += getPlaygroundSizeX();
00161     }
00162     else if (pos.x >= getPlaygroundSizeX())
00163     {
00164         pos.x -= getPlaygroundSizeX();
00165         targetPos.x -= getPlaygroundSizeX();
00166     }
00167     if (pos.y < 0)
00168     {
00169         pos.y += getPlaygroundSizeY();
00170         targetPos.y += getPlaygroundSizeY();
00171     }
00172     else if (pos.y >= getPlaygroundSizeY())
00173     {
00174         pos.y -= getPlaygroundSizeY();
00175         targetPos.y -= getPlaygroundSizeY();
00176     }
00177 }
00178 
00179 void BasicMobility::placeRandomlyIfOutside(Coord& targetPos)
00180 {
00181     if (pos.x<0 || pos.x>=getPlaygroundSizeX() || pos.y<0 || pos.y>=getPlaygroundSizeY())
00182     {
00183         Coord newPos = getRandomPosition();
00184         targetPos += newPos - pos;
00185         pos = newPos;
00186     }
00187 }
00188 
00189 void BasicMobility::raiseErrorIfOutside()
00190 {
00191     if (pos.x<0 || pos.x>=getPlaygroundSizeX() || pos.y<0 || pos.y>=getPlaygroundSizeY())
00192     {
00193         error("node moved outside the playground of size %gx%g (x=%g,y=%g)",
00194               getPlaygroundSizeX(), getPlaygroundSizeY(), pos.x, pos.y);
00195     }
00196 }
00197 
00198 void BasicMobility::handleIfOutside(BorderPolicy policy, Coord& targetPos, Coord& step, double& angle)
00199 {
00200     switch (policy)
00201     {
00202         case REFLECT:       reflectIfOutside(targetPos, step, angle); break;
00203         case WRAP:          wrapIfOutside(targetPos); break;
00204         case PLACERANDOMLY: placeRandomlyIfOutside(targetPos); break;
00205         case RAISEERROR:    raiseErrorIfOutside(); break;
00206     }
00207 }