group-mobility.cc

00001 /*
00002  * Copyright (c) 2008 Regents of the SIGNET lab, University of Padova.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University of Padova (SIGNET lab) nor the 
00014  *    names of its contributors may be used to endorse or promote products 
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
00019  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00020  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
00021  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00022  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00023  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00024  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00025  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00026  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00027  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include"group-mobility.h"
00031 #include<node-core.h>
00032 #include<rng.h>
00033 
00034 /* ======================================================================
00035    TCL Hooks for the simulator
00036    ====================================================================== */
00037 static class GroupMobPositionClass : public TclClass {
00038         public:
00039                 GroupMobPositionClass() : TclClass("Position/GroupMob") {}
00040                 TclObject* create(int, const char*const*) {
00041                         return (new GroupMobPosition());
00042                 }
00043 } class_groupmobposition;
00044 
00045 
00046 void UpdatePosTimer::expire(Event *e)
00047 {
00048         module->update(Scheduler::instance().clock());
00049 }
00050 
00051 
00052 
00053 GroupMobPosition::GroupMobPosition() : 
00054         Position(),
00055         xFieldWidth_(0),
00056         yFieldWidth_(0),
00057         alpha_(0),
00058         speedMean_(0),
00059         sigmaSpeed_(0),
00060         speedM_(0),
00061         speedS_(0),
00062         eta_(0),
00063         charge_(0),
00064         memoryM_(0),
00065         memoryS_(0),
00066         bound_(REBOUNCE),
00067         updateTime_(0),
00068         debug_(0),
00069         speed_(0),
00070         leader_(0),
00071         updateTmr_(this)
00072 {
00073         bind("xFieldWidth_", &xFieldWidth_);
00074         bind("yFieldWidth_", &yFieldWidth_);
00075         bind("alpha_", &alpha_);
00076         bind("updateTime_", &updateTime_);
00077         bind("speedMean_",&speedMean_);
00078         bind("sigmaSpeed_",&sigmaSpeed_);
00079         bind("speedM_",&speedM_);
00080         bind("speedS_",&speedS_);
00081         bind("eta_",&eta_);
00082         bind("charge_",&charge_);
00083         bind("memoryM_",&memoryM_);
00084         bind("memoryS_",&memoryS_);
00085         bind("thetaMax_",&thetaMax_);
00086         bind("debug_", &debug_);
00087 }
00088 
00089 GroupMobPosition::~GroupMobPosition()
00090 {
00091 }
00092 
00093 
00094 int GroupMobPosition::command(int argc, const char*const* argv)
00095 {
00096         Tcl& tcl = Tcl::instance();
00097         if (argc == 2)
00098         {
00099                 if(strcasecmp(argv[1], "move") == 0)
00100                 {
00101                         if (updateTime_<0)
00102                         {
00103                                 fprintf(stderr,"Error GroupMobPosition(constructor) updateTime_ <= 0");
00104                                 return TCL_ERROR;
00105                         }
00106                         speed_ = speedMean_;
00107                         steps_ = memoryM_;
00108                         gammaOld_ = RNG::defaultrng()->uniform_double() * (2*pi);
00109                         updateTmr_.resched(updateTime_);
00110                         return TCL_OK;
00111                 }
00112                 else if(strcasecmp(argv[1], "stop") == 0)
00113                 {
00114                         updateTmr_.cancel();
00115                         return TCL_OK;
00116                 }
00117         }
00118         else if(argc == 3)
00119         {
00120                 if(strcasecmp(argv[1], "bound") == 0)
00121                 {
00122                         if (strcasecmp(argv[2],"SPHERIC")==0)
00123                                 bound_ = SPHERIC;
00124                         else
00125                         {
00126                                 if (strcasecmp(argv[2],"THOROIDAL")==0)
00127                                         bound_ = THOROIDAL;
00128                                 else
00129                                 {
00130                                         if (strcasecmp(argv[2],"HARDWALL")==0)
00131                                                 bound_ = HARDWALL;
00132                                         else
00133                                         {
00134                                                 if (strcasecmp(argv[2],"REBOUNCE")==0)
00135                                                         bound_ = REBOUNCE;
00136                                                 else
00137                                                 {
00138                                                         fprintf(stderr,"GMPosition::command(%s), unrecognized bound_ type (%s)\n",argv[1],argv[2]);
00139                                                         exit(1);
00140                                                 }
00141                                         }
00142                                 }
00143                         }
00144                         return TCL_OK;
00145                 }
00146                 else if(strcasecmp(argv[1], "leader") == 0)
00147                 {
00148                         Position* lead = (Position *)TclObject::lookup(argv[2]);
00149                         leader_ = lead;
00150                         return TCL_OK;
00151                 }
00152         }
00153         return Position::command(argc, argv);
00154 }
00155 
00156 
00157 double GroupMobPosition::getX()
00158 {
00159         return (x_);
00160 }
00161 
00162 double GroupMobPosition::getY()
00163 {
00164         return (y_);
00165 }
00166 
00167 
00168 double GroupMobPosition::distance(Position* pos1, Position* pos2)
00169 {
00170         double xdiff,ydiff;
00171         double dist;
00172     
00173         xdiff = pos1->getX() - pos2->getX();
00174         ydiff = pos1->getY() - pos2->getY();
00175         // if bounds are spheric, compute the shortest distance separating 
00176         // the two nodes in the spheric (wrapped) 2D plane
00177         if(bound_==SPHERIC){
00178                 xdiff = (fabs(xdiff)<((xFieldWidth_)/2))? xdiff : (xFieldWidth_-fabs(xdiff));
00179                 ydiff = (fabs(ydiff)<((yFieldWidth_)/2))? ydiff : (yFieldWidth_-fabs(ydiff));
00180         }
00181         //printf("Compute Distance:%f\n",sqrt(xdiff*xdiff + ydiff*ydiff));
00182         return (sqrt(xdiff*xdiff + ydiff*ydiff));
00183 }
00184 
00185 
00186 double GroupMobPosition::mirror_posx(double xnode, double xleader)
00187 {
00188 
00189         double d, dref;
00190 
00191         d       = fabs(xnode - xleader);
00192         dref    = (xFieldWidth_)/2.;
00193         
00194         // if the two nodes are separated more than half of the max.
00195         // distance, then we consider the wrapped coordinate of the leader
00196         // to compute the attraction between leader and the current node
00197         // the same applies in the procedure below
00198 
00199         if ( (d>dref) && (bound_==SPHERIC) )
00200                 return ( xleader - (xFieldWidth_)*(sgn(xleader-xnode)) );
00201 
00202         return xleader;
00203 }
00204 
00205 double GroupMobPosition::mirror_posy(double ynode, double yleader)
00206 {
00207 
00208         double d, dref;
00209 
00210         d       = fabs(ynode - yleader);
00211         dref    = (yFieldWidth_)/2.;
00212         
00213         // if the two nodes are separated more than half of the max.
00214         // distance, then we consider the wrapped coordinate of the leader
00215         // to compute the attraction between leader and the current node
00216         // the same applies in the procedure below
00217 
00218         if ( (d>dref) && (bound_==SPHERIC) ) 
00219                 return ( yleader - (yFieldWidth_)*(sgn(yleader-ynode)) );
00220 
00221         return yleader;
00222 }
00223 
00224 
00225 double GroupMobPosition::MobGaussian(double avrg, double sigma)
00226 {
00227 
00228         double x1, x2, w, y1;
00229         static double y2;
00230         static int use_last = 0;
00231 
00232         if(sigma==0.0)
00233                 return(avrg);
00234 
00235         if (use_last) {
00236                 y1 = y2;
00237                 use_last = 0;
00238         }
00239         else {
00240                 do {
00241                         x1 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00242                         x2 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00243                         w = x1 * x1 + x2 * x2;
00244                 } while ( w >= 1.0 );
00245 
00246                 w = sqrt( (-2.0 * log( w ) ) / w );
00247                 y1 = x1 * w;
00248                 y2 = x2 * w;
00249                 use_last = 1;
00250         }
00251         if(y1*sigma+avrg<0.0)
00252                 return(0.0);
00253         else
00254                 return ((double)(y1*sigma+avrg));
00255 }
00256 
00257 
00258 // double Gauss(double m,double sigma,int type){
00259 //      static int cache=0;
00260 //      static float v1;
00261 //      float v2,w,y;
00262 // 
00263 //      if(cache){
00264 //              cache=0;
00265 //              return v1*sigma+m;
00266 //      }
00267 //      else{
00268 //              do{
00269 //                      v1=2.0*RNG::defaultrng()->uniform_double()-1.0;
00270 //                      v2=2.0*RNG::defaultrng()->uniform_double()-1.0;
00271 //                      w=(v1*v1)+(v2*v2);
00272 //              }while(w>1.0);
00273 //              y=sqrt((-2.0*log(w))/w);
00274 //              v1=v1*y;
00275 //              cache=1;
00276 //              return v2*y*sigma+m;
00277 //      }
00278 // }
00279 
00280 
00281 void GroupMobPosition::update(double now)
00282 {
00283         if (debug_>10) printf("old pos (%f,%f)...", getX(), getY());
00284         double alpha,speed,gamma,rho,delta;
00285         int rmem;
00286         double newx,newy,xPrec,yPrec;
00287         double ro;
00288 
00289         speed_ = speed_*(1.-eta_) + 
00290                         eta_*MobGaussian(speedMean_, sigmaSpeed_);
00291         rho = speed_ * updateTime_;
00292 
00293         gamma = gammaOld_;
00294         if (steps_>=1) steps_--;
00295         else
00296         {
00297                 rmem = (int)((RNG::defaultrng()->uniform_double()*2*memoryS_)-memoryS_);
00298                 steps_ = (int)((rmem<memoryM_)?0:memoryM_+rmem);
00299                 delta = (RNG::defaultrng()->uniform_double()*thetaMax_);
00300                 gamma += 2*delta-thetaMax_;
00301                 gammaOld_ = gamma;
00302         }
00303         
00304         if (gamma>pi)   gamma -= 2*pi;
00305         if (gamma<pi)   gamma += 2*pi;
00306         
00307         // Compute new indepent position
00308         x_ += rho*cos(gamma);
00309         y_ += rho*sin(gamma);
00310         
00311         // Add Leader Attraction
00312         if (leader_!=0)
00313         {
00314                 double cx,cy,dist;
00315                 double charge_g=0.8;
00316                 double charge_l=0.8;
00317 
00318                 cx = mirror_posx(x_,leader_->getX());
00319                 cy = mirror_posy(y_,leader_->getY());
00320 
00321                 dist = distance(leader_,this);
00322                 if ((alpha_>0)&&(dist<1)) dist =1;              // limit the force field to avoid explosion of velocity
00323                 rho = updateTime_*MobGaussian(speedM_,speedS_)*charge_*((GroupMobPosition*)leader_)->getCharge()*pow(dist,-alpha_);
00324                 
00325                 if (cx-x_==0) gamma = pi/2*sgn((cy-y_));
00326                 else gamma = atan((cy-y_)/(cx-x_));
00327                 if ((cx-x_)<=0.0) gamma += (y_-cy)>=0.0?pi:-pi;
00328                 
00329                 x_ += rho*cos(gamma);
00330                 y_ += rho*sin(gamma);
00331 
00332         }// End Leader Attraction
00333 
00334         // adjust new position according to bounds behaviour
00335 
00336         xPrec= xprec_;
00337         yPrec= yprec_;
00338         newx = x_;
00339         newy = y_;
00340 
00341 
00342         if ((newy>yFieldWidth_) || (newy<0)){
00343                 switch (bound_) {
00344                         case SPHERIC:           yPrec           -=yFieldWidth_*(sgn(newy));
00345                         newy            -=yFieldWidth_*(sgn(newy));
00346                         break;
00347                         case THOROIDAL: xPrec           = (xFieldWidth_/2) + xPrec - newx;
00348                         yPrec           = (yFieldWidth_/2) + yPrec - newy;
00349                         newx            = xFieldWidth_/2;
00350                         newy            = yFieldWidth_/2;
00351                         break;
00352                         case HARDWALL:          newy=newy<0?0:yFieldWidth_; break;
00353                         case REBOUNCE:          if (newy>yFieldWidth_){
00354                                 newy    = 2*yFieldWidth_ - newy;
00355                                 yPrec   = 2*yFieldWidth_ - yPrec;
00356                         }else{
00357                                 newy    = 0 - newy;
00358                                 yPrec   = 0 - yPrec;
00359                         }
00360                                                                 
00361                         gammaOld_ *= -1;
00362                                                                         /*if (newy<0){
00363                         if (newx-xPrec>0)
00364                         plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00365                         else plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00366                 }else{
00367                         if (newx-xPrec>0)
00368                         plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00369                         else plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00370                 }*/
00371                         break;
00372                 }
00373         }
00374         if ((newx>xFieldWidth_) || (newx<0)){
00375                 switch (bound_) {
00376                         case SPHERIC:           xPrec           -=xFieldWidth_*(sgn(newx));
00377                         newx            -=xFieldWidth_*(sgn(newx));
00378                         break;
00379                         case THOROIDAL: xPrec           = (xFieldWidth_/2) + xPrec - newx;
00380                         yPrec           = (yFieldWidth_/2) + yPrec - newy;
00381                         newx            = xFieldWidth_/2;
00382                         newy            = yFieldWidth_/2;
00383                         break;
00384                         case HARDWALL:          newx=newx<0?0:xFieldWidth_; break;
00385                         case REBOUNCE:          if (newx>xFieldWidth_){
00386                                 newx    = 2*xFieldWidth_ - newx;
00387                                 xPrec   = 2*xFieldWidth_ - xPrec;
00388                         }else{
00389                                 newx    = 0 - newx;
00390                                 xPrec   = 0 - xPrec;
00391                         }
00392                         if (newy==yPrec){
00393                                 if (newx>xPrec)
00394                                         gammaOld_ = 0;
00395                                 else 
00396                                         gammaOld_ = pi;
00397                         }else{
00398                                 if (newy>yPrec)
00399                                         gammaOld_ = pi - gammaOld_;
00400                                 else 
00401                                         gammaOld_ = -pi - gammaOld_;
00402                         }
00403                         break;
00404                 }
00405         }
00406 
00407 
00408         if ((newx<0.0)||(newx>xFieldWidth_)|| (newy<0.0)||(newy>yFieldWidth_))
00409         {
00410                 puts("[GroupMobPosition::update] Errate position! Abort!");
00411                 exit(1);
00412         }
00413 
00414         x_ = newx;
00415         y_ = newy;
00416         if (debug_>10) printf("new pos (%f,%f)\n", x_, y_);
00417         updateTmr_.resched(updateTime_);
00418         
00419 //      FILE *fd;
00420 //      char filename[100];
00421 //      sprintf(filename,"movementTraceNode%d.out",debug_);
00422 //      fd = fopen(filename,"a");
00423 //      fprintf(fd,"%f\t%f\n", x_, y_);
00424 //      fclose(fd);
00425 }

Generated on Wed Nov 26 15:47:28 2008 for NS-MIRACLE library by  doxygen 1.5.2