00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
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
00068
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
00081
00082
00083
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
00097
00098 node->update_position();
00099
00100
00101
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
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_);
00138 LIST_INIT(&ifhead_);
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
00181
00182
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
00207
00208 energy_model()->node_on() = false;
00209
00210
00211
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
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
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
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
00361
00362
00363
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();
00417
00418 destX_ = x;
00419 destY_ = y;
00420 speed_ = s;
00421
00422 dX_ = destX_ - X_;
00423 dY_ = destY_ - Y_;
00424 dZ_ = 0.0;
00425
00426 if (destX_ != X_ || destY_ != Y_) {
00427
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
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
00471
00472 if ((interval == 0.0)&&(position_update_time_!=0))
00473 return;
00474
00475
00476
00477 X_ += dX_ * (speed_ * interval);
00478 Y_ += dY_ * (speed_ * interval);
00479
00480 if ((dX_ > 0 && X_ > destX_) || (dX_ < 0 && X_ < destX_))
00481 X_ = destX_;
00482 if ((dY_ > 0 && Y_ > destY_) || (dY_ < 0 && Y_ < destY_))
00483 Y_ = destY_;
00484
00485
00486 if(oldX != X_)
00487 T_->updateNodesList(this, oldX);
00488
00489
00490
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
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;
00547
00548
00549
00550
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();
00587 m->update_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 , float )
00604 {
00605 }