mobilenode.cc

Go to the documentation of this file.
00001 /*-*-   Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
00002  *
00003  * Copyright (c) 1997 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *  This product includes software developed by the Computer Systems
00017  *  Engineering Group at Lawrence Berkeley Laboratory.
00018  * 4. Neither the name of the University nor of the Laboratory may be used
00019  *    to endorse or promote products derived from this software without
00020  *    specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00023  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00025  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00026  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00027  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00028  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00029  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00031  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00032  * SUCH DAMAGE.
00033  *
00034  * $Header: /nfs/jade/vint/CVSROOT/ns-2/common/mobilenode.cc,v 1.35 2005/01/13 18:33:47 haldar Exp $
00035  *
00036  * Code in this file will be changed in the near future. From now on it 
00037  * should be treated as for backward compatibility only, although it is in
00038  * active use by many other code in ns. - Aug 29, 2000
00039  */
00040 
00041 /* 
00042  * CMU-Monarch project's Mobility extensions ported by Padma Haldar, 
00043  * 11/98.
00044  */
00045 
00046 
00047 #include <math.h>
00048 #include <stdlib.h>
00049 
00050 #include "connector.h"
00051 #include "delay.h"
00052 #include "packet.h"
00053 #include "random.h"
00054 #include "trace.h"
00055 #include "address.h"
00056 
00057 #include "arp.h"
00058 #include "topography.h"
00059 #include "ll.h"
00060 #include "mac.h"
00061 #include "propagation.h"
00062 #include "mobilenode.h"
00063 #include "phy.h"
00064 #include "wired-phy.h"
00065 #include "god.h"
00066 
00067 // XXX Must supply the first parameter in the macro otherwise msvc
00068 // is unhappy. 
00069 static LIST_HEAD(_dummy_MobileNodeList, MobileNode) nodehead = { 0 };
00070 
00071 static class MobileNodeClass : public TclClass {
00072 public:
00073         MobileNodeClass() : TclClass("Node/MobileNode") {}
00074         TclObject* create(int, const char*const*) {
00075                 return (new MobileNode);
00076         }
00077 } class_mobilenode;
00078 
00079 /*
00080  *  PositionHandler()
00081  *
00082  *  Updates the position of a mobile node every N seconds, where N is
00083  *  based upon the speed of the mobile and the resolution of the topography.
00084  *
00085  */
00086 void
00087 PositionHandler::handle(Event*)
00088 {
00089     Scheduler& s = Scheduler::instance();
00090 
00091 #if 0
00092     fprintf(stderr, "*** POSITION HANDLER for node %d (time: %f) ***\n",
00093         node->address(), s.clock());
00094 #endif
00095     /*
00096      * Update current location
00097      */
00098     node->update_position();
00099 
00100     /*
00101      * Choose a new random speed and direction
00102      */
00103 #ifdef DEBUG
00104         fprintf(stderr, "%d - %s: calling random_destination()\n",
00105                 node->address_, __PRETTY_FUNCTION__);
00106 #endif
00107     node->random_destination();
00108 
00109     s.schedule(&node->pos_handle_, &node->pos_intr_,
00110            node->position_update_interval_);
00111 }
00112 
00113 
00114 /* ======================================================================
00115    Mobile Node
00116    ====================================================================== */
00117 
00118 MobileNode::MobileNode(void) : 
00119     pos_handle_(this)
00120 {
00121     X_ = Y_ = Z_ = speed_ = 0.0;
00122     dX_ = dY_ = dZ_ = 0.0;
00123     destX_ = destY_ = 0.0;
00124 
00125     random_motion_ = 0;
00126     base_stn_ = -1;
00127     T_ = 0;
00128 
00129     log_target_ = 0;
00130     next_ = 0;
00131     radius_ = 0;
00132 
00133     position_update_interval_ = MN_POSITION_UPDATE_INTERVAL;
00134     position_update_time_ = 0.0;
00135     
00136 
00137     LIST_INSERT_HEAD(&nodehead, this, link_);   // node list
00138     LIST_INIT(&ifhead_);                // interface list
00139     bind("X_", &X_);
00140     bind("Y_", &Y_);
00141     bind("Z_", &Z_);
00142     bind("speed_", &speed_);
00143     
00144 }
00145 
00146 int
00147 MobileNode::command(int argc, const char*const* argv)
00148 {
00149     Tcl& tcl = Tcl::instance();
00150     if(argc == 2) {
00151         if(strcmp(argv[1], "start") == 0) {
00152                 start();
00153             return TCL_OK;
00154         } else if(strcmp(argv[1], "log-movement") == 0) {
00155 #ifdef DEBUG
00156                         fprintf(stderr,
00157                                 "%d - %s: calling update_position()\n",
00158                                 address_, __PRETTY_FUNCTION__);
00159 #endif
00160                 update_position();
00161                 log_movement();
00162             return TCL_OK;
00163         } else if(strcmp(argv[1], "log-energy") == 0) {
00164             log_energy(1);
00165             return TCL_OK;
00166         } else if(strcmp(argv[1], "powersaving") == 0) {
00167             energy_model()->powersavingflag() = 1;
00168             energy_model()->start_powersaving();
00169             return TCL_OK;
00170         } else if(strcmp(argv[1], "adaptivefidelity") == 0) {
00171             energy_model()->adaptivefidelity() = 1;
00172             energy_model()->powersavingflag() = 1;
00173             energy_model()->start_powersaving();
00174             return TCL_OK;
00175         } else if (strcmp(argv[1], "energy") == 0) {
00176             Tcl& tcl = Tcl::instance();
00177             tcl.resultf("%f", energy_model()->energy());
00178             return TCL_OK;
00179         } else if (strcmp(argv[1], "adjustenergy") == 0) {
00180             // assume every 10 sec schedule and 1.15 W 
00181             // idle energy consumption. needs to be
00182             // parameterized.
00183             idle_energy_patch(10, 1.15);
00184             energy_model()->total_sndtime() = 0;
00185             energy_model()->total_rcvtime() = 0;
00186             energy_model()->total_sleeptime() = 0;
00187             return TCL_OK;
00188         } else if (strcmp(argv[1], "on") == 0) {
00189             energy_model()->node_on() = true;
00190             tcl.evalf("%s set netif_(0)", name_);
00191             const char *str = tcl.result();
00192             tcl.evalf("%s NodeOn", str);
00193             God::instance()->ComputeRoute();
00194             return TCL_OK;
00195         } else if (strcmp(argv[1], "off") == 0) {
00196             energy_model()->node_on() = false;
00197             tcl.evalf("%s set netif_(0)", name_);
00198             const char *str = tcl.result();
00199             tcl.evalf("%s NodeOff", str);
00200             tcl.evalf("%s set ragent_", name_);
00201             str = tcl.result();
00202             tcl.evalf("%s reset-state", str);
00203             God::instance()->ComputeRoute();
00204                 return TCL_OK;
00205         } else if (strcmp(argv[1], "shutdown") == 0) {
00206             // set node state
00207             //Phy *p;
00208             energy_model()->node_on() = false;
00209             
00210             //p = ifhead().lh_first;
00211             //if (p) ((WirelessPhy *)p)->node_off();
00212             return TCL_OK;
00213         } else if (strcmp(argv[1], "startup") == 0) {
00214             energy_model()->node_on() = true;
00215             return TCL_OK;
00216         }
00217     
00218     } else if(argc == 3) {
00219         if(strcmp(argv[1], "addif") == 0) {
00220             WiredPhy* phyp = (WiredPhy*)TclObject::lookup(argv[2]);
00221             if(phyp == 0)
00222                 return TCL_ERROR;
00223             phyp->insertnode(&ifhead_);
00224             phyp->setnode(this);
00225             return TCL_OK;
00226         } else if (strcmp(argv[1], "setsleeptime") == 0) {
00227             energy_model()->afe()->set_sleeptime(atof(argv[2]));
00228             energy_model()->afe()->set_sleepseed(atof(argv[2]));
00229             return TCL_OK;
00230         } else if (strcmp(argv[1], "setenergy") == 0) {
00231             energy_model()->setenergy(atof(argv[2]));
00232             return TCL_OK;
00233         } else if (strcmp(argv[1], "settalive") == 0) {
00234             energy_model()->max_inroute_time() = atof(argv[2]);
00235             return TCL_OK;
00236         } else if (strcmp(argv[1], "maxttl") == 0) {
00237             energy_model()->maxttl() = atoi(argv[2]);
00238             return TCL_OK;
00239         } else if(strcmp(argv[1], "radius") == 0) {
00240                         radius_ = strtod(argv[2],NULL);
00241                         return TCL_OK;
00242                 } else if(strcmp(argv[1], "random-motion") == 0) {
00243             random_motion_ = atoi(argv[2]);
00244             return TCL_OK;
00245         } else if(strcmp(argv[1], "addif") == 0) {
00246             WirelessPhy *n = (WirelessPhy*)
00247                 TclObject::lookup(argv[2]);
00248             if(n == 0)
00249                 return TCL_ERROR;
00250             n->insertnode(&ifhead_);
00251             n->setnode(this);
00252             return TCL_OK;
00253         } else if(strcmp(argv[1], "topography") == 0) {
00254             T_ = (Topography*) TclObject::lookup(argv[2]);
00255             if (T_ == 0)
00256                 return TCL_ERROR;
00257             return TCL_OK;
00258         } else if(strcmp(argv[1], "log-target") == 0) {
00259             log_target_ = (Trace*) TclObject::lookup(argv[2]);
00260             if (log_target_ == 0)
00261                 return TCL_ERROR;
00262             return TCL_OK;
00263         } else if (strcmp(argv[1],"base-station") == 0) {
00264             base_stn_ = atoi(argv[2]);
00265             if(base_stn_ == -1)
00266                 return TCL_ERROR;
00267             return TCL_OK;
00268         } 
00269     } else if (argc == 4) {
00270         if (strcmp(argv[1], "idleenergy") == 0) {
00271             idle_energy_patch(atof(argv[2]),atof(argv[3]));
00272             return TCL_OK;
00273         }
00274     } else if (argc == 5) {
00275         if (strcmp(argv[1], "setdest") == 0) { 
00276             /* <mobilenode> setdest <X> <Y> <speed> */
00277 #ifdef DEBUG
00278             fprintf(stderr, "%d - %s: calling set_destination()\n",
00279                 address_, __FUNCTION__);
00280 #endif
00281   
00282             if (set_destination(atof(argv[2]), atof(argv[3]), 
00283                         atof(argv[4])) < 0)
00284                 return TCL_ERROR;
00285             return TCL_OK;
00286         }
00287     }
00288     return Node::command(argc, argv);
00289 }
00290 
00291 
00292 /* ======================================================================
00293    Other class functions
00294    ====================================================================== */
00295 void
00296 MobileNode::dump(void)
00297 {
00298     Phy *n;
00299     fprintf(stdout, "Index: %d\n", address_);
00300     fprintf(stdout, "Network Interface List\n");
00301     for(n = ifhead_.lh_first; n; n = n->nextnode() )
00302         n->dump();  
00303     fprintf(stdout, "--------------------------------------------------\n");
00304 }
00305 
00306 /* ======================================================================
00307    Position Functions
00308    ====================================================================== */
00309 void 
00310 MobileNode::start()
00311 {
00312     Scheduler& s = Scheduler::instance();
00313 
00314     if(random_motion_ == 0) {
00315         log_movement();
00316         return;
00317     }
00318 
00319     assert(initialized());
00320 
00321     random_position();
00322 #ifdef DEBUG
00323         fprintf(stderr, "%d - %s: calling random_destination()\n",
00324                 address_, __PRETTY_FUNCTION__);
00325 #endif
00326     random_destination();
00327     s.schedule(&pos_handle_, &pos_intr_, position_update_interval_);
00328 }
00329 
00330 void 
00331 MobileNode::log_movement()
00332 {
00333         if (!log_target_) 
00334         return;
00335 
00336     Scheduler& s = Scheduler::instance();
00337     sprintf(log_target_->pt_->buffer(),
00338         "M %.5f %d (%.2f, %.2f, %.2f), (%.2f, %.2f), %.2f",
00339         s.clock(), address_, X_, Y_, Z_, destX_, destY_, speed_);
00340     log_target_->pt_->dump();
00341 }
00342 
00343 
00344 void
00345 MobileNode::log_energy(int flag)
00346 {
00347     if (!log_target_) 
00348         return;
00349     Scheduler &s = Scheduler::instance();
00350     if (flag) {
00351         sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e %f", s.clock(),
00352             address_, energy_model_->energy()); 
00353     } else {
00354         sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e 0 ", s.clock(),
00355             address_); 
00356     }
00357     log_target_->pt_->dump();
00358 }
00359 
00360 //void
00361 //MobileNode::logrttime(double t)
00362 //{
00363 //  last_rt_time_ = (int)t;
00364 //}
00365 
00366 void
00367 MobileNode::bound_position()
00368 {
00369     double minX;
00370     double maxX;
00371     double minY;
00372     double maxY;
00373     int recheck = 1;
00374 
00375     assert(T_ != 0);
00376 
00377     minX = T_->lowerX();
00378     maxX = T_->upperX();
00379     minY = T_->lowerY();
00380     maxY = T_->upperY();
00381 
00382     while (recheck) {
00383         recheck = 0;
00384         if (X_ < minX) {
00385             X_ = minX + (minX - X_);
00386             recheck = 1;
00387         }
00388         if (X_ > maxX) {
00389             X_ = maxX - (X_ - maxX);
00390             recheck = 1;
00391         }
00392         if (Y_ < minY) {
00393             Y_ = minY + (minY - Y_);
00394             recheck = 1;
00395         }
00396         if (Y_ > maxY) {
00397             Y_ = maxY- (Y_ - maxY);
00398             recheck = 1;
00399         }
00400         if (recheck) {
00401             fprintf(stderr, "Adjust position of node %d\n",address_);
00402         }
00403     }
00404 }
00405 
00406 int
00407 MobileNode::set_destination(double x, double y, double s)
00408 {
00409     assert(initialized());
00410 
00411     if(x >= T_->upperX() || x <= T_->lowerX())
00412         return -1;
00413     if(y >= T_->upperY() || y <= T_->lowerY())
00414         return -1;
00415     
00416     update_position();  // figure out where we are now
00417     
00418     destX_ = x;
00419     destY_ = y;
00420     speed_ = s;
00421     
00422     dX_ = destX_ - X_;
00423     dY_ = destY_ - Y_;
00424     dZ_ = 0.0;      // this isn't used, since flying isn't allowed
00425 
00426     if (destX_ != X_ || destY_ != Y_) {
00427         // normalize dx, dy to unit len
00428         double len = sqrt( (dX_ * dX_) + (dY_ * dY_) );
00429         dX_ /= len;
00430         dY_ /= len;
00431     }
00432   
00433     position_update_time_ = Scheduler::instance().clock();
00434 
00435 #ifdef DEBUG
00436     fprintf(stderr, "%d - %s: calling log_movement()\n", 
00437         address_, __FUNCTION__);
00438 #endif
00439     log_movement();
00440 
00441     /* update gridkeeper */
00442     if (GridKeeper::instance()){
00443         GridKeeper* gp =  GridKeeper::instance();
00444         gp-> new_moves(this);
00445     }                     
00446 
00447     if (namChan_ != 0) {
00448         sprintf(nwrk_,     
00449             "n -t %f -s %d -x %f -y %f -U %f -V %f -T %f",
00450             Scheduler::instance().clock(),
00451             nodeid_,
00452             X_, Y_,
00453             speed_ * dX_, speed_ * dY_,
00454             ((speed_*dX_) != 0) ? 
00455                 (destX_-X_)/(speed_*dX_) : speed_*dX_
00456             );   
00457         namdump();         
00458     }
00459     return 0;
00460 }
00461 
00462 
00463 
00464 void 
00465 MobileNode::update_position()
00466 {
00467     double now = Scheduler::instance().clock();
00468     double interval = now - position_update_time_;
00469     double oldX = X_;
00470     //double oldY = Y_;
00471 
00472     if ((interval == 0.0)&&(position_update_time_!=0))
00473         return;         // ^^^ for list-based imprvmnt 
00474 
00475 
00476     // CHECK, IF THE SPEED IS 0, THEN SKIP, but usually it's not 0
00477     X_ += dX_ * (speed_ * interval);
00478     Y_ += dY_ * (speed_ * interval);
00479 
00480     if ((dX_ > 0 && X_ > destX_) || (dX_ < 0 && X_ < destX_))
00481       X_ = destX_;      // correct overshoot (slow? XXX)
00482     if ((dY_ > 0 && Y_ > destY_) || (dY_ < 0 && Y_ < destY_))
00483       Y_ = destY_;      // correct overshoot (slow? XXX)
00484     
00485     /* list based improvement */
00486     if(oldX != X_)// || oldY != Y_)
00487         T_->updateNodesList(this, oldX);//, oldY);
00488     // COMMENTED BY -VAL- // bound_position();
00489 
00490     // COMMENTED BY -VAL- // Z_ = T_->height(X_, Y_);
00491 
00492 #if 0
00493     fprintf(stderr, "Node: %d, X: %6.2f, Y: %6.2f, Z: %6.2f, time: %f\n",
00494         address_, X_, Y_, Z_, now);
00495 #endif
00496     position_update_time_ = now;
00497 }
00498 
00499 
00500 void
00501 MobileNode::random_position()
00502 {
00503     if (T_ == 0) {
00504         fprintf(stderr, "No TOPOLOGY assigned\n");
00505         exit(1);
00506     }
00507 
00508     X_ = Random::uniform() * T_->upperX();
00509     Y_ = Random::uniform() * T_->upperY();
00510     Z_ = T_->height(X_, Y_);
00511 
00512     position_update_time_ = 0.0;
00513 }
00514 
00515 void
00516 MobileNode::random_destination()
00517 {
00518     if (T_ == 0) {
00519         fprintf(stderr, "No TOPOLOGY assigned\n");
00520         exit(1);
00521     }
00522 
00523     random_speed();
00524 #ifdef DEBUG
00525         fprintf(stderr, "%d - %s: calling set_destination()\n",
00526                 address_, __FUNCTION__);
00527 #endif
00528     (void) set_destination(Random::uniform() * T_->upperX(),
00529                                Random::uniform() * T_->upperY(),
00530                                speed_);
00531 }
00532 
00533 void
00534 MobileNode::random_direction()
00535 {
00536     /* this code isn't used anymore -dam 1/22/98 */
00537     double len;
00538 
00539     dX_ = (double) Random::random();
00540     dY_ = (double) Random::random();
00541 
00542     len = sqrt( (dX_ * dX_) + (dY_ * dY_) );
00543 
00544     dX_ /= len;
00545     dY_ /= len;
00546     dZ_ = 0.0;              // we're not flying...
00547 
00548     /*
00549      * Determine the sign of each component of the
00550      * direction vector.
00551      */
00552     if (X_ > (T_->upperX() - 2*T_->resol())) {
00553         if (dX_ > 0) 
00554             dX_ = -dX_;
00555     } else if (X_ < (T_->lowerX() + 2*T_->resol())) {
00556         if (dX_ < 0) 
00557             dX_ = -dX_;
00558     } else if (Random::uniform() <= 0.5) {
00559         dX_ = -dX_;
00560     }
00561 
00562     if (Y_ > (T_->upperY() - 2*T_->resol())) {
00563         if (dY_ > 0) 
00564             dY_ = -dY_;
00565     } else if (Y_ < (T_->lowerY() + 2*T_->resol())) {
00566         if (dY_ < 0) 
00567             dY_ = -dY_;
00568     } else if(Random::uniform() <= 0.5) {
00569         dY_ = -dY_;
00570     }
00571 #if 0
00572     fprintf(stderr, "Location: (%f, %f), Direction: (%f, %f)\n",
00573         X_, Y_, dX_, dY_);
00574 #endif
00575 }
00576 
00577 void
00578 MobileNode::random_speed()
00579 {
00580     speed_ = Random::uniform() * MAX_SPEED;
00581 }
00582 
00583 double
00584 MobileNode::distance(MobileNode *m)
00585 {
00586     update_position();      // update my position
00587     m->update_position();       // update m's position
00588 
00589         double Xpos = (X_ - m->X_) * (X_ - m->X_);
00590         double Ypos = (Y_ - m->Y_) * (Y_ - m->Y_);
00591     double Zpos = (Z_ - m->Z_) * (Z_ - m->Z_);
00592 
00593         return sqrt(Xpos + Ypos + Zpos);
00594 }
00595 
00596 double
00597 MobileNode::propdelay(MobileNode *m)
00598 {
00599     return distance(m) / SPEED_OF_LIGHT;
00600 }
00601 
00602 void 
00603 MobileNode::idle_energy_patch(float /*total*/, float /*P_idle*/)
00604 {
00605 }

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6