gmposition.cc

00001 /*
00002  * Copyright (c) 2007 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<rng.h>
00031 #include "gmposition.h"
00032 
00033 
00034 /* ======================================================================
00035    TCL Hooks for the simulator
00036    ====================================================================== */
00037 static class GMPositionClass : public TclClass {
00038 public:
00039         GMPositionClass() : TclClass("Position/GM") {}
00040         TclObject* create(int, const char*const*) {
00041                 return (new GMPosition());
00042         }
00043 } class_gmposition;
00044 
00045 GMPosition::GMPosition() : 
00046         Position(),
00047         xFieldWidth_(0),
00048         yFieldWidth_(0),
00049         alpha_(0),
00050         speedMean_(0),
00051         directionMean_(0),
00052         bound_(REBOUNCE),
00053         updateTime_(0),
00054         debug_(0),
00055         speed_(0),
00056         direction_(0),
00057         nextUpdateTime_(0.0)
00058 {
00059         bind("xFieldWidth_", &xFieldWidth_);
00060         bind("yFieldWidth_", &yFieldWidth_);
00061         bind("alpha_", &alpha_);
00062         bind("directionMean_", &directionMean_);
00063         bind("updateTime_", &updateTime_);
00064         bind("debug_", &debug_);
00065 }
00066 
00067 GMPosition::~GMPosition()
00068 {
00069 }
00070 
00071 int GMPosition::command(int argc, const char*const* argv)
00072 {
00073         Tcl& tcl = Tcl::instance();
00074         if(argc == 3)
00075         {
00076                 if(strcasecmp(argv[1], "bound") == 0)
00077                 {
00078                         if (strcasecmp(argv[2],"SPHERIC")==0)
00079                                 bound_ = SPHERIC;
00080                         else
00081                         {
00082                                 if (strcasecmp(argv[2],"THOROIDAL")==0)
00083                                         bound_ = THOROIDAL;
00084                                 else
00085                                 {
00086                                         if (strcasecmp(argv[2],"HARDWALL")==0)
00087                                                 bound_ = HARDWALL;
00088                                         else
00089                                         {
00090                                                 if (strcasecmp(argv[2],"REBOUNCE")==0)
00091                                                         bound_ = REBOUNCE;
00092                                                 else
00093                                                 {
00094                                                         fprintf(stderr,"GMPosition::command(%s), unrecognized bound_ type (%s)\n",argv[1],argv[2]);
00095                                                         exit(1);
00096                                                 }
00097                                         }
00098                                 }
00099                         }
00100                         return TCL_OK;
00101                 }
00102                 if(strcasecmp(argv[1], "speedMean") == 0)
00103                 {
00104                         speedMean_ = speed_ = atof(argv[2]);
00105                         return TCL_OK;
00106                 }
00107         }
00108         return Position::command(argc, argv);
00109 }
00110 
00111 
00112 double GMPosition::Gaussian()
00113 {
00114         double x1, x2, w, y1;
00115         static double y2;
00116         static int use_last = 0;
00117 
00118         if (use_last)             
00119         {
00120                 y1 = y2;
00121                 use_last = 0;
00122         }
00123         else
00124         {
00125                 do
00126                 {
00127 //                      x1 = 2.0 * ((float)rand()/(float)RAND_MAX) - 1.0;
00128 //                      x2 = 2.0 * ((float)rand()/(float)RAND_MAX) - 1.0;
00129                         x1 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00130                         x2 = 2.0 * RNG::defaultrng()->uniform_double() - 1.0;
00131                         w = x1 * x1 + x2 * x2;
00132                 } while ( w >= 1.0 );
00133 
00134                 w = sqrt( (-2.0 * log( w ) ) / w );
00135                 y1 = x1 * w;
00136                 y2 = x2 * w;
00137                 use_last = 1;
00138         }
00139         return(y1);
00140 }
00141 
00142 void GMPosition::update(double now)
00143 {
00144         double t;
00145         for(t = nextUpdateTime_; t < now; t += updateTime_)
00146         {
00147                 // calculate new sample of speed and direction
00148                 if (debug_>10)
00149                         printf("Update at %.3f(%.3f) old speed %.2f old direction %.2f", now, t, speed_, direction_);
00150                 
00151                 speed_ = (alpha_*speed_) + (((1.0-alpha_))*speedMean_) + (sqrt(1.0-pow(alpha_,2.0))*Gaussian());
00152                 direction_ = (alpha_*direction_) + (((1.0-alpha_))*directionMean_) + (sqrt(1.0-pow(alpha_,2.0))*Gaussian());
00153                 //direction_ = (alpha_*direction_) + (sqrt(1.0-pow(alpha_,2.0))*Gaussian());
00154                 if (debug_>10)
00155                         printf(" new speed %.2f new direction %.2f \n", speed_, direction_);
00156                 // calculate new position
00157                 double newx = x_ + (speed_*cos(direction_)*updateTime_);
00158                 double newy = y_ + (speed_*sin(direction_)*updateTime_);
00159                 if (debug_>10)
00160                         printf("X:%.3f->%.3f Y:%.3f->%.3f\n", x_, newx, y_, newy);
00161                 // verify whether the new position has to be re-computed in order
00162                 // to maintain node position within the simulation field        
00163                 
00164                 if ((newy>yFieldWidth_) || (newy<0))
00165                 {
00166                         switch (bound_)
00167                         {
00168                         case SPHERIC:
00169                                 y_ -= yFieldWidth_*(sgn(newy));
00170                                 newy -= yFieldWidth_*(sgn(newy));
00171                                 break;
00172                         case THOROIDAL:
00173                                 x_ = (xFieldWidth_/2) + x_ - newx;
00174                                 y_ = (yFieldWidth_/2) + y_ - newy;
00175                                 newx = xFieldWidth_/2;
00176                                 newy = yFieldWidth_/2;
00177                                 break;
00178                         case HARDWALL:
00179                                 newy = newy<0?0:yFieldWidth_; 
00180                                 break;
00181                         case REBOUNCE:
00182                                 if (newy>yFieldWidth_)
00183                                 {
00184                                         newy = 2*yFieldWidth_ - newy;
00185                                         y_ = 2*yFieldWidth_ - y_;
00186                                 }else{
00187                                         newy = 0 - newy;
00188                                         y_ = 0 - y_;
00189                                 }
00190                                 direction_ *= -1;
00191                                 /*if (newy<0){
00192                                         if (newx-x_>0)
00193                                                 plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00194                                         else plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00195                                 }else{
00196                                         if (newx-x_>0)
00197                                                 plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00198                                         else plStPtr->gammaOld = -1 * plStPtr->gammaOld;
00199                                 }*/
00200                                 break;
00201                         }
00202                 }
00203                 if ((newx>xFieldWidth_) || (newx<0))
00204                 {
00205                         switch (bound_)
00206                         {
00207                         case SPHERIC:
00208                                 x_ -= xFieldWidth_*(sgn(newx));
00209                                 newx -= xFieldWidth_*(sgn(newx));
00210                                 break;
00211                         case THOROIDAL:
00212                                 x_ = (xFieldWidth_/2) + x_ - newx;
00213                                 y_ = (yFieldWidth_/2) + y_ - newy;
00214                                 newx = xFieldWidth_/2;
00215                                 newy = yFieldWidth_/2;
00216                                 break;
00217                         case HARDWALL:
00218                                 newx = newx<0?0:xFieldWidth_;
00219                                 break;
00220                         case REBOUNCE:
00221                                 if (newx>xFieldWidth_)
00222                                 {
00223                                         newx = 2*xFieldWidth_ - newx;
00224                                         x_ = 2*xFieldWidth_ - x_;
00225                                 }else{
00226                                         newx = 0 - newx;
00227                                         x_ = 0 - x_;
00228                                 }
00229                                 if (newy==y_)
00230                                 {
00231                                         if (newx>x_)
00232                                                 direction_ = 0;
00233                                         else
00234                                                 direction_ = pi;
00235                                 }else{
00236                                         if (newy>y_)
00237                                                 direction_ = pi - direction_;
00238                                         else 
00239                                                 direction_ = -pi - direction_;
00240                                 }
00241                                 break;
00242                         }
00243                 }
00244                 x_ = newx;
00245                 y_ = newy;
00246                 directionMean_ = direction_;
00247         }
00248         nextUpdateTime_ = t;
00249         if (debug_>10)
00250                 printf("nextUpdateTime = %f, now %f, updateTime %f\n", nextUpdateTime_, now, updateTime_);
00251 }
00252 
00253 double GMPosition::getX()
00254 {
00255         double now = Scheduler::instance().clock();
00256         if (now > nextUpdateTime_)
00257                 update(now);
00258         return (x_);
00259 }
00260 
00261 double GMPosition::getY()
00262 {
00263         double now = Scheduler::instance().clock();
00264         if (now > nextUpdateTime_)
00265                 update(now);
00266         return (y_);
00267 }

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