📄 mobilenode.cc
字号:
/*-*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- * * Copyright (c) 1997 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Header: /nfs/jade/vint/CVSROOT/ns-2/common/mobilenode.cc,v 1.29 2002/05/06 17:10:40 difa Exp $ * * Code in this file will be changed in the near future. From now on it * should be treated as for backward compatibility only, although it is in * active use by many other code in ns. - Aug 29, 2000 *//* * CMU-Monarch project's Mobility extensions ported by Padma Haldar, * 11/98. */#include <math.h>#include <stdlib.h>#include "connector.h"#include "delay.h"#include "packet.h"#include "random.h"#include "trace.h"#include "address.h"#include "arp.h"#include "topography.h"#include "ll.h"#include "mac.h"#include "propagation.h"#include "mobilenode.h"#include "phy.h"#include "wired-phy.h"#include "god.h"// XXX Must supply the first parameter in the macro otherwise msvc// is unhappy. static LIST_HEAD(_dummy_MobileNodeList, MobileNode) nodehead = { 0 };static class MobileNodeClass : public TclClass {public: MobileNodeClass() : TclClass("Node/MobileNode") {} TclObject* create(int, const char*const*) { return (new MobileNode); }} class_mobilenode;/* * PositionHandler() * * Updates the position of a mobile node every N seconds, where N is * based upon the speed of the mobile and the resolution of the topography. * */voidPositionHandler::handle(Event*){ Scheduler& s = Scheduler::instance();#if 0 fprintf(stderr, "*** POSITION HANDLER for node %d (time: %f) ***\n", node->address(), s.clock());#endif /* * Update current location */ node->update_position(); /* * Choose a new random speed and direction */#ifdef DEBUG fprintf(stderr, "%d - %s: calling random_destination()\n", node->address_, __PRETTY_FUNCTION__);#endif node->random_destination(); s.schedule(&node->pos_handle_, &node->pos_intr_, node->position_update_interval_);}/* ====================================================================== Mobile Node ====================================================================== */MobileNode::MobileNode(void) : pos_handle_(this){ X_ = Y_ = Z_ = speed_ = 0.0; dX_ = dY_ = dZ_ = 0.0; destX_ = destY_ = 0.0; random_motion_ = 0; base_stn_ = -1; T_ = 0; log_target_ = 0; next_ = 0; radius_ = 0; position_update_interval_ = POSITION_UPDATE_INTERVAL; position_update_time_ = 0.0; LIST_INSERT_HEAD(&nodehead, this, link_); // node list LIST_INIT(&ifhead_); // interface list bind("X_", &X_); bind("Y_", &Y_); bind("Z_", &Z_); bind("speed_", &speed_);}intMobileNode::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if(argc == 2) { if(strcmp(argv[1], "start") == 0) { start(); return TCL_OK; } else if(strcmp(argv[1], "log-movement") == 0) {#ifdef DEBUG fprintf(stderr, "%d - %s: calling update_position()\n", address_, __PRETTY_FUNCTION__);#endif update_position(); log_movement(); return TCL_OK; } else if(strcmp(argv[1], "log-energy") == 0) { log_energy(1); return TCL_OK; } else if(strcmp(argv[1], "powersaving") == 0) { energy_model()->powersavingflag() = 1; energy_model()->start_powersaving(); return TCL_OK; } else if(strcmp(argv[1], "adaptivefidelity") == 0) { energy_model()->adaptivefidelity() = 1; energy_model()->powersavingflag() = 1; energy_model()->start_powersaving(); return TCL_OK; } else if (strcmp(argv[1], "energy") == 0) { Tcl& tcl = Tcl::instance(); tcl.resultf("%f", energy_model()->energy()); return TCL_OK; } else if (strcmp(argv[1], "adjustenergy") == 0) { // assume every 10 sec schedule and 1.15 W // idle energy consumption. needs to be // parameterized. idle_energy_patch(10, 1.15); energy_model()->total_sndtime() = 0; energy_model()->total_rcvtime() = 0; energy_model()->total_sleeptime() = 0; return TCL_OK; } else if (strcmp(argv[1], "on") == 0) { energy_model()->node_on() = true; tcl.evalf("%s set netif_(0)", name_); char *str = tcl.result(); tcl.evalf("%s NodeOn", str); God::instance()->ComputeRoute(); return TCL_OK; } else if (strcmp(argv[1], "off") == 0) { energy_model()->node_on() = false; tcl.evalf("%s set netif_(0)", name_); char *str = tcl.result(); tcl.evalf("%s NodeOff", str); tcl.evalf("%s set ragent_", name_); str = tcl.result(); tcl.evalf("%s reset-state", str); God::instance()->ComputeRoute(); return TCL_OK; } else if (strcmp(argv[1], "shutdown") == 0) { // set node state //Phy *p; energy_model()->node_on() = false; //p = ifhead().lh_first; //if (p) ((WirelessPhy *)p)->node_off(); return TCL_OK; } else if (strcmp(argv[1], "startup") == 0) { energy_model()->node_on() = true; return TCL_OK; } } else if(argc == 3) { if(strcmp(argv[1], "addif") == 0) { WiredPhy* phyp = (WiredPhy*)TclObject::lookup(argv[2]); if(phyp == 0) return TCL_ERROR; phyp->insertnode(&ifhead_); phyp->setnode(this); return TCL_OK; } else if (strcmp(argv[1], "setsleeptime") == 0) { energy_model()->afe()->set_sleeptime(atof(argv[2])); energy_model()->afe()->set_sleepseed(atof(argv[2])); return TCL_OK; } else if (strcmp(argv[1], "setenergy") == 0) { energy_model()->setenergy(atof(argv[2])); return TCL_OK; } else if (strcmp(argv[1], "settalive") == 0) { energy_model()->max_inroute_time() = atof(argv[2]); return TCL_OK; } else if (strcmp(argv[1], "maxttl") == 0) { energy_model()->maxttl() = atoi(argv[2]); return TCL_OK; } else if(strcmp(argv[1], "radius") == 0) { radius_ = strtod(argv[2],NULL); return TCL_OK; } else if(strcmp(argv[1], "random-motion") == 0) { random_motion_ = atoi(argv[2]); return TCL_OK; } else if(strcmp(argv[1], "addif") == 0) { WirelessPhy *n = (WirelessPhy*) TclObject::lookup(argv[2]); if(n == 0) return TCL_ERROR; n->insertnode(&ifhead_); n->setnode(this); return TCL_OK; } else if(strcmp(argv[1], "topography") == 0) { T_ = (Topography*) TclObject::lookup(argv[2]); if (T_ == 0) return TCL_ERROR; return TCL_OK; } else if(strcmp(argv[1], "log-target") == 0) { log_target_ = (Trace*) TclObject::lookup(argv[2]); if (log_target_ == 0) return TCL_ERROR; return TCL_OK; } else if (strcmp(argv[1],"base-station") == 0) { base_stn_ = atoi(argv[2]); if(base_stn_ == -1) return TCL_ERROR; return TCL_OK; } } else if (argc == 4) { if (strcmp(argv[1], "idleenergy") == 0) { idle_energy_patch(atof(argv[2]),atof(argv[3])); return TCL_OK; } } else if (argc == 5) { if (strcmp(argv[1], "setdest") == 0) { /* <mobilenode> setdest <X> <Y> <speed> */#ifdef DEBUG fprintf(stderr, "%d - %s: calling set_destination()\n", address_, __FUNCTION__);#endif if (set_destination(atof(argv[2]), atof(argv[3]), atof(argv[4])) < 0) return TCL_ERROR; return TCL_OK; } } return Node::command(argc, argv);}/* ====================================================================== Other class functions ====================================================================== */voidMobileNode::dump(void){ Phy *n; fprintf(stdout, "Index: %d\n", address_); fprintf(stdout, "Network Interface List\n"); for(n = ifhead_.lh_first; n; n = n->nextnode() ) n->dump(); fprintf(stdout, "--------------------------------------------------\n");}/* ====================================================================== Position Functions ====================================================================== */void MobileNode::start(){ Scheduler& s = Scheduler::instance(); if(random_motion_ == 0) { log_movement(); return; } assert(initialized()); random_position();#ifdef DEBUG fprintf(stderr, "%d - %s: calling random_destination()\n", address_, __PRETTY_FUNCTION__);#endif random_destination(); s.schedule(&pos_handle_, &pos_intr_, position_update_interval_);}void MobileNode::log_movement(){ if (!log_target_) return; Scheduler& s = Scheduler::instance(); sprintf(log_target_->pt_->buffer(), "M %.5f %d (%.2f, %.2f, %.2f), (%.2f, %.2f), %.2f", s.clock(), address_, X_, Y_, Z_, destX_, destY_, speed_); log_target_->pt_->dump();}voidMobileNode::log_energy(int flag){ if (!log_target_) return; Scheduler &s = Scheduler::instance(); if (flag) { sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e %f", s.clock(), address_, energy_model_->energy()); } else { sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e 0 ", s.clock(), address_); } log_target_->pt_->dump();}//void//MobileNode::logrttime(double t)//{// last_rt_time_ = (int)t;//}voidMobileNode::bound_position(){ double minX; double maxX; double minY; double maxY; int recheck = 1; assert(T_ != 0); minX = T_->lowerX(); maxX = T_->upperX(); minY = T_->lowerY(); maxY = T_->upperY(); while (recheck) { recheck = 0; if (X_ < minX) { X_ = minX + (minX - X_); recheck = 1; } if (X_ > maxX) { X_ = maxX - (X_ - maxX); recheck = 1; } if (Y_ < minY) { Y_ = minY + (minY - Y_); recheck = 1; } if (Y_ > maxY) { Y_ = maxY- (Y_ - maxY); recheck = 1; } if (recheck) { fprintf(stderr, "Adjust position of node %d\n",address_); } }}intMobileNode::set_destination(double x, double y, double s){ assert(initialized()); if(x >= T_->upperX() || x <= T_->lowerX()) return -1; if(y >= T_->upperY() || y <= T_->lowerY()) return -1; update_position(); // figure out where we are now destX_ = x; destY_ = y; speed_ = s; dX_ = destX_ - X_; dY_ = destY_ - Y_; dZ_ = 0.0; // this isn't used, since flying isn't allowed if (destX_ != X_ || destY_ != Y_) { // normalize dx, dy to unit len double len = sqrt( (dX_ * dX_) + (dY_ * dY_) ); dX_ /= len; dY_ /= len; } position_update_time_ = Scheduler::instance().clock();#ifdef DEBUG fprintf(stderr, "%d - %s: calling log_movement()\n", address_, __FUNCTION__);#endif log_movement(); /* update gridkeeper */ if (GridKeeper::instance()){ GridKeeper* gp = GridKeeper::instance(); gp-> new_moves(this); } if (namChan_ != 0) { sprintf(nwrk_, "n -t %f -s %d -x %f -y %f -u %f -v %f -T %f", Scheduler::instance().clock(), nodeid_, X_, Y_, speed_ * dX_, speed_ * dY_, ((speed_*dX_) != 0) ? (destX_-X_)/(speed_*dX_) : speed_*dX_ ); namdump(); } return 0;}void MobileNode::update_position(){ double now = Scheduler::instance().clock(); double interval = now - position_update_time_; if (interval == 0.0) return; X_ += dX_ * (speed_ * interval); Y_ += dY_ * (speed_ * interval); if ((dX_ > 0 && X_ > destX_) || (dX_ < 0 && X_ < destX_)) X_ = destX_; // correct overshoot (slow? XXX) if ((dY_ > 0 && Y_ > destY_) || (dY_ < 0 && Y_ < destY_)) Y_ = destY_; // correct overshoot (slow? XXX) bound_position(); Z_ = T_->height(X_, Y_);#if 0 fprintf(stderr, "Node: %d, X: %6.2f, Y: %6.2f, Z: %6.2f, time: %f\n", address_, X_, Y_, Z_, now);#endif position_update_time_ = now;}voidMobileNode::random_position(){ if (T_ == 0) { fprintf(stderr, "No TOPOLOGY assigned\n"); exit(1); } X_ = Random::uniform() * T_->upperX(); Y_ = Random::uniform() * T_->upperY(); Z_ = T_->height(X_, Y_); position_update_time_ = 0.0;}voidMobileNode::random_destination(){ if (T_ == 0) { fprintf(stderr, "No TOPOLOGY assigned\n"); exit(1); } random_speed();#ifdef DEBUG fprintf(stderr, "%d - %s: calling set_destination()\n", address_, __FUNCTION__);#endif (void) set_destination(Random::uniform() * T_->upperX(), Random::uniform() * T_->upperY(), speed_);}voidMobileNode::random_direction(){ /* this code isn't used anymore -dam 1/22/98 */ double len; dX_ = (double) Random::random(); dY_ = (double) Random::random(); len = sqrt( (dX_ * dX_) + (dY_ * dY_) ); dX_ /= len; dY_ /= len; dZ_ = 0.0; // we're not flying... /* * Determine the sign of each component of the * direction vector. */ if (X_ > (T_->upperX() - 2*T_->resol())) { if (dX_ > 0) dX_ = -dX_; } else if (X_ < (T_->lowerX() + 2*T_->resol())) { if (dX_ < 0) dX_ = -dX_; } else if (Random::uniform() <= 0.5) { dX_ = -dX_; } if (Y_ > (T_->upperY() - 2*T_->resol())) { if (dY_ > 0) dY_ = -dY_; } else if (Y_ < (T_->lowerY() + 2*T_->resol())) { if (dY_ < 0) dY_ = -dY_; } else if(Random::uniform() <= 0.5) { dY_ = -dY_; }#if 0 fprintf(stderr, "Location: (%f, %f), Direction: (%f, %f)\n", X_, Y_, dX_, dY_);#endif}voidMobileNode::random_speed(){ speed_ = Random::uniform() * MAX_SPEED;}doubleMobileNode::distance(MobileNode *m){ update_position(); // update my position m->update_position(); // update m's position double Xpos = (X_ - m->X_) * (X_ - m->X_); double Ypos = (Y_ - m->Y_) * (Y_ - m->Y_); double Zpos = (Z_ - m->Z_) * (Z_ - m->Z_); return sqrt(Xpos + Ypos + Zpos);}doubleMobileNode::propdelay(MobileNode *m){ return distance(m) / SPEED_OF_LIGHT;}void MobileNode::idle_energy_patch(float /*total*/, float /*P_idle*/){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -