mobilenode.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*-*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
  2.  *
  3.  * Copyright (c) 1997 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory.
  18.  * 4. Neither the name of the University nor of the Laboratory may be used
  19.  *    to endorse or promote products derived from this software without
  20.  *    specific prior written permission.
  21.  *
  22.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32.  * SUCH DAMAGE.
  33.  *
  34.  * $Header: /cvsroot/nsnam/ns-2/common/mobilenode.cc,v 1.36 2006/02/22 13:21:52 mahrenho Exp $
  35.  *
  36.  * Code in this file will be changed in the near future. From now on it 
  37.  * should be treated as for backward compatibility only, although it is in
  38.  * active use by many other code in ns. - Aug 29, 2000
  39.  */
  40. /* 
  41.  * CMU-Monarch project's Mobility extensions ported by Padma Haldar, 
  42.  * 11/98.
  43.  */
  44. #include <math.h>
  45. #include <stdlib.h>
  46. #include "connector.h"
  47. #include "delay.h"
  48. #include "packet.h"
  49. #include "random.h"
  50. #include "trace.h"
  51. #include "address.h"
  52. #include "arp.h"
  53. #include "topography.h"
  54. #include "ll.h"
  55. #include "mac.h"
  56. #include "propagation.h"
  57. #include "mobilenode.h"
  58. #include "phy.h"
  59. #include "wired-phy.h"
  60. #include "god.h"
  61. // XXX Must supply the first parameter in the macro otherwise msvc
  62. // is unhappy. 
  63. static LIST_HEAD(_dummy_MobileNodeList, MobileNode) nodehead = { 0 };
  64. static class MobileNodeClass : public TclClass {
  65. public:
  66.         MobileNodeClass() : TclClass("Node/MobileNode") {}
  67.         TclObject* create(int, const char*const*) {
  68.                 return (new MobileNode);
  69.         }
  70. } class_mobilenode;
  71. /*
  72.  *  PositionHandler()
  73.  *
  74.  *  Updates the position of a mobile node every N seconds, where N is
  75.  *  based upon the speed of the mobile and the resolution of the topography.
  76.  *
  77.  */
  78. void
  79. PositionHandler::handle(Event*)
  80. {
  81. Scheduler& s = Scheduler::instance();
  82. #if 0
  83. fprintf(stderr, "*** POSITION HANDLER for node %d (time: %f) ***n",
  84. node->address(), s.clock());
  85. #endif
  86. /*
  87.  * Update current location
  88.  */
  89. node->update_position();
  90. /*
  91.  * Choose a new random speed and direction
  92.  */
  93. #ifdef DEBUG
  94.         fprintf(stderr, "%d - %s: calling random_destination()n",
  95.                 node->address_, __PRETTY_FUNCTION__);
  96. #endif
  97. node->random_destination();
  98. s.schedule(&node->pos_handle_, &node->pos_intr_,
  99.    node->position_update_interval_);
  100. }
  101. /* ======================================================================
  102.    Mobile Node
  103.    ====================================================================== */
  104. MobileNode::MobileNode(void) : 
  105. pos_handle_(this)
  106. {
  107. X_ = Y_ = Z_ = speed_ = 0.0;
  108. dX_ = dY_ = dZ_ = 0.0;
  109. destX_ = destY_ = 0.0;
  110. random_motion_ = 0;
  111. base_stn_ = -1;
  112. T_ = 0;
  113. log_target_ = 0;
  114. next_ = 0;
  115. radius_ = 0;
  116. position_update_interval_ = MN_POSITION_UPDATE_INTERVAL;
  117. position_update_time_ = 0.0;
  118. LIST_INSERT_HEAD(&nodehead, this, link_); // node list
  119. LIST_INIT(&ifhead_); // interface list
  120. bind("X_", &X_);
  121. bind("Y_", &Y_);
  122. bind("Z_", &Z_);
  123. bind("speed_", &speed_);
  124. }
  125. int
  126. MobileNode::command(int argc, const char*const* argv)
  127. {
  128. Tcl& tcl = Tcl::instance();
  129. if(argc == 2) {
  130. if(strcmp(argv[1], "start") == 0) {
  131.         start();
  132. return TCL_OK;
  133. } else if(strcmp(argv[1], "log-movement") == 0) {
  134. #ifdef DEBUG
  135.                         fprintf(stderr,
  136.                                 "%d - %s: calling update_position()n",
  137.                                 address_, __PRETTY_FUNCTION__);
  138. #endif
  139.         update_position();
  140.         log_movement();
  141. return TCL_OK;
  142. } else if(strcmp(argv[1], "log-energy") == 0) {
  143. log_energy(1);
  144. return TCL_OK;
  145. } else if(strcmp(argv[1], "powersaving") == 0) {
  146. energy_model()->powersavingflag() = 1;
  147. energy_model()->start_powersaving();
  148. return TCL_OK;
  149. } else if(strcmp(argv[1], "adaptivefidelity") == 0) {
  150. energy_model()->adaptivefidelity() = 1;
  151. energy_model()->powersavingflag() = 1;
  152. energy_model()->start_powersaving();
  153. return TCL_OK;
  154. } else if (strcmp(argv[1], "energy") == 0) {
  155. Tcl& tcl = Tcl::instance();
  156. tcl.resultf("%f", energy_model()->energy());
  157. return TCL_OK;
  158. } else if (strcmp(argv[1], "adjustenergy") == 0) {
  159. // assume every 10 sec schedule and 1.15 W 
  160. // idle energy consumption. needs to be
  161. // parameterized.
  162. idle_energy_patch(10, 1.15);
  163. energy_model()->total_sndtime() = 0;
  164. energy_model()->total_rcvtime() = 0;
  165. energy_model()->total_sleeptime() = 0;
  166. return TCL_OK;
  167. } else if (strcmp(argv[1], "on") == 0) {
  168. energy_model()->node_on() = true;
  169. tcl.evalf("%s set netif_(0)", name_);
  170. const char *str = tcl.result();
  171. tcl.evalf("%s NodeOn", str);
  172. God::instance()->ComputeRoute();
  173. return TCL_OK;
  174. } else if (strcmp(argv[1], "off") == 0) {
  175. energy_model()->node_on() = false;
  176. tcl.evalf("%s set netif_(0)", name_);
  177. const char *str = tcl.result();
  178. tcl.evalf("%s NodeOff", str);
  179. tcl.evalf("%s set ragent_", name_);
  180. str = tcl.result();
  181. tcl.evalf("%s reset-state", str);
  182. God::instance()->ComputeRoute();
  183.       return TCL_OK;
  184. } else if (strcmp(argv[1], "shutdown") == 0) {
  185. // set node state
  186. //Phy *p;
  187. energy_model()->node_on() = false;
  188. //p = ifhead().lh_first;
  189. //if (p) ((WirelessPhy *)p)->node_off();
  190. return TCL_OK;
  191. } else if (strcmp(argv[1], "startup") == 0) {
  192. energy_model()->node_on() = true;
  193. return TCL_OK;
  194. }
  195. } else if(argc == 3) {
  196. if(strcmp(argv[1], "addif") == 0) {
  197. WiredPhy* phyp = (WiredPhy*)TclObject::lookup(argv[2]);
  198. if(phyp == 0)
  199. return TCL_ERROR;
  200. phyp->insertnode(&ifhead_);
  201. phyp->setnode(this);
  202. return TCL_OK;
  203. } else if (strcmp(argv[1], "setsleeptime") == 0) {
  204. energy_model()->afe()->set_sleeptime(atof(argv[2]));
  205. energy_model()->afe()->set_sleepseed(atof(argv[2]));
  206. return TCL_OK;
  207. } else if (strcmp(argv[1], "setenergy") == 0) {
  208. energy_model()->setenergy(atof(argv[2]));
  209. return TCL_OK;
  210. } else if (strcmp(argv[1], "settalive") == 0) {
  211. energy_model()->max_inroute_time() = atof(argv[2]);
  212. return TCL_OK;
  213. } else if (strcmp(argv[1], "maxttl") == 0) {
  214. energy_model()->maxttl() = atoi(argv[2]);
  215. return TCL_OK;
  216. } else if(strcmp(argv[1], "radius") == 0) {
  217.                         radius_ = strtod(argv[2],NULL);
  218.                         return TCL_OK;
  219.                 } else if(strcmp(argv[1], "random-motion") == 0) {
  220. random_motion_ = atoi(argv[2]);
  221. return TCL_OK;
  222. } else if(strcmp(argv[1], "addif") == 0) {
  223. WirelessPhy *n = (WirelessPhy*)
  224. TclObject::lookup(argv[2]);
  225. if(n == 0)
  226. return TCL_ERROR;
  227. n->insertnode(&ifhead_);
  228. n->setnode(this);
  229. return TCL_OK;
  230. } else if(strcmp(argv[1], "topography") == 0) {
  231. T_ = (Topography*) TclObject::lookup(argv[2]);
  232. if (T_ == 0)
  233. return TCL_ERROR;
  234. return TCL_OK;
  235. } else if(strcmp(argv[1], "log-target") == 0) {
  236. log_target_ = (Trace*) TclObject::lookup(argv[2]);
  237. if (log_target_ == 0)
  238. return TCL_ERROR;
  239. return TCL_OK;
  240. } else if (strcmp(argv[1],"base-station") == 0) {
  241. base_stn_ = atoi(argv[2]);
  242. if(base_stn_ == -1)
  243. return TCL_ERROR;
  244. return TCL_OK;
  245. } else if (argc == 4) {
  246. if (strcmp(argv[1], "idleenergy") == 0) {
  247. idle_energy_patch(atof(argv[2]),atof(argv[3]));
  248. return TCL_OK;
  249. }
  250. } else if (argc == 5) {
  251. if (strcmp(argv[1], "setdest") == 0) { 
  252. /* <mobilenode> setdest <X> <Y> <speed> */
  253. #ifdef DEBUG
  254. fprintf(stderr, "%d - %s: calling set_destination()n",
  255. address_, __FUNCTION__);
  256. #endif
  257.   
  258. if (set_destination(atof(argv[2]), atof(argv[3]), 
  259.     atof(argv[4])) < 0)
  260. return TCL_ERROR;
  261. return TCL_OK;
  262. }
  263. }
  264. return Node::command(argc, argv);
  265. }
  266. /* ======================================================================
  267.    Other class functions
  268.    ====================================================================== */
  269. void
  270. MobileNode::dump(void)
  271. {
  272. Phy *n;
  273. fprintf(stdout, "Index: %dn", address_);
  274. fprintf(stdout, "Network Interface Listn");
  275.   for(n = ifhead_.lh_first; n; n = n->nextnode() )
  276. n->dump();
  277. fprintf(stdout, "--------------------------------------------------n");
  278. }
  279. /* ======================================================================
  280.    Position Functions
  281.    ====================================================================== */
  282. void 
  283. MobileNode::start()
  284. {
  285. Scheduler& s = Scheduler::instance();
  286. if(random_motion_ == 0) {
  287. log_movement();
  288. return;
  289. }
  290. assert(initialized());
  291. random_position();
  292. #ifdef DEBUG
  293.         fprintf(stderr, "%d - %s: calling random_destination()n",
  294.                 address_, __PRETTY_FUNCTION__);
  295. #endif
  296. random_destination();
  297. s.schedule(&pos_handle_, &pos_intr_, position_update_interval_);
  298. }
  299. void 
  300. MobileNode::log_movement()
  301. {
  302.         if (!log_target_) 
  303. return;
  304. Scheduler& s = Scheduler::instance();
  305. sprintf(log_target_->pt_->buffer(),
  306. "M %.5f %d (%.2f, %.2f, %.2f), (%.2f, %.2f), %.2f",
  307. s.clock(), address_, X_, Y_, Z_, destX_, destY_, speed_);
  308. log_target_->pt_->dump();
  309. }
  310. void
  311. MobileNode::log_energy(int flag)
  312. {
  313. if (!log_target_) 
  314. return;
  315. Scheduler &s = Scheduler::instance();
  316. if (flag) {
  317. sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e %f", s.clock(),
  318. address_, energy_model_->energy()); 
  319. } else {
  320. sprintf(log_target_->pt_->buffer(),"N -t %f -n %d -e 0 ", s.clock(),
  321. address_); 
  322. }
  323. log_target_->pt_->dump();
  324. }
  325. //void
  326. //MobileNode::logrttime(double t)
  327. //{
  328. // last_rt_time_ = (int)t;
  329. //}
  330. void
  331. MobileNode::bound_position()
  332. {
  333. double minX;
  334. double maxX;
  335. double minY;
  336. double maxY;
  337. int recheck = 1;
  338. assert(T_ != 0);
  339. minX = T_->lowerX();
  340. maxX = T_->upperX();
  341. minY = T_->lowerY();
  342. maxY = T_->upperY();
  343. while (recheck) {
  344. recheck = 0;
  345. if (X_ < minX) {
  346. X_ = minX + (minX - X_);
  347. recheck = 1;
  348. }
  349. if (X_ > maxX) {
  350. X_ = maxX - (X_ - maxX);
  351. recheck = 1;
  352. }
  353. if (Y_ < minY) {
  354. Y_ = minY + (minY - Y_);
  355. recheck = 1;
  356. }
  357. if (Y_ > maxY) {
  358. Y_ = maxY- (Y_ - maxY);
  359. recheck = 1;
  360. }
  361. if (recheck) {
  362. fprintf(stderr, "Adjust position of node %dn",address_);
  363. }
  364. }
  365. }
  366. int
  367. MobileNode::set_destination(double x, double y, double s)
  368. {
  369. assert(initialized());
  370. if(x >= T_->upperX() || x <= T_->lowerX())
  371. return -1;
  372. if(y >= T_->upperY() || y <= T_->lowerY())
  373. return -1;
  374. update_position(); // figure out where we are now
  375. destX_ = x;
  376. destY_ = y;
  377. speed_ = s;
  378. dX_ = destX_ - X_;
  379. dY_ = destY_ - Y_;
  380. dZ_ = 0.0; // this isn't used, since flying isn't allowed
  381. double len;
  382. if (destX_ != X_ || destY_ != Y_) {
  383. // normalize dx, dy to unit len
  384. len = sqrt( (dX_ * dX_) + (dY_ * dY_) );
  385. dX_ /= len;
  386. dY_ /= len;
  387. }
  388.   
  389. position_update_time_ = Scheduler::instance().clock();
  390. #ifdef DEBUG
  391. fprintf(stderr, "%d - %s: calling log_movement()n", 
  392. address_, __FUNCTION__);
  393. #endif
  394. log_movement();
  395. /* update gridkeeper */
  396. if (GridKeeper::instance()){
  397. GridKeeper* gp =  GridKeeper::instance();
  398. gp-> new_moves(this);
  399. }                     
  400. if (namChan_ != 0) {
  401. double v = speed_ * sqrt( (dX_ * dX_) + (dY_ * dY_)); 
  402. sprintf(nwrk_,     
  403. "n -t %f -s %d -x %f -y %f -U %f -V %f -T %f",
  404. Scheduler::instance().clock(),
  405. nodeid_,
  406. X_, Y_,
  407. speed_ * dX_, speed_ * dY_,
  408. ( v != 0) ? len / v : 0. );   
  409. namdump();         
  410. }
  411. return 0;
  412. }
  413. void 
  414. MobileNode::update_position()
  415. {
  416. double now = Scheduler::instance().clock();
  417. double interval = now - position_update_time_;
  418. double oldX = X_;
  419. //double oldY = Y_;
  420. if ((interval == 0.0)&&(position_update_time_!=0))
  421. return;         // ^^^ for list-based imprvmnt 
  422. // CHECK, IF THE SPEED IS 0, THEN SKIP, but usually it's not 0
  423. X_ += dX_ * (speed_ * interval);
  424. Y_ += dY_ * (speed_ * interval);
  425. if ((dX_ > 0 && X_ > destX_) || (dX_ < 0 && X_ < destX_))
  426.   X_ = destX_; // correct overshoot (slow? XXX)
  427. if ((dY_ > 0 && Y_ > destY_) || (dY_ < 0 && Y_ < destY_))
  428.   Y_ = destY_; // correct overshoot (slow? XXX)
  429. /* list based improvement */
  430. if(oldX != X_)// || oldY != Y_)
  431. T_->updateNodesList(this, oldX);//, oldY);
  432. // COMMENTED BY -VAL- // bound_position();
  433. // COMMENTED BY -VAL- // Z_ = T_->height(X_, Y_);
  434. #if 0
  435. fprintf(stderr, "Node: %d, X: %6.2f, Y: %6.2f, Z: %6.2f, time: %fn",
  436. address_, X_, Y_, Z_, now);
  437. #endif
  438. position_update_time_ = now;
  439. }
  440. void
  441. MobileNode::random_position()
  442. {
  443. if (T_ == 0) {
  444. fprintf(stderr, "No TOPOLOGY assignedn");
  445. exit(1);
  446. }
  447. X_ = Random::uniform() * T_->upperX();
  448. Y_ = Random::uniform() * T_->upperY();
  449. Z_ = T_->height(X_, Y_);
  450. position_update_time_ = 0.0;
  451. }
  452. void
  453. MobileNode::random_destination()
  454. {
  455. if (T_ == 0) {
  456. fprintf(stderr, "No TOPOLOGY assignedn");
  457. exit(1);
  458. }
  459. random_speed();
  460. #ifdef DEBUG
  461.         fprintf(stderr, "%d - %s: calling set_destination()n",
  462.                 address_, __FUNCTION__);
  463. #endif
  464. (void) set_destination(Random::uniform() * T_->upperX(),
  465.                                Random::uniform() * T_->upperY(),
  466.                                speed_);
  467. }
  468. void
  469. MobileNode::random_direction()
  470. {
  471. /* this code isn't used anymore -dam 1/22/98 */
  472. double len;
  473. dX_ = (double) Random::random();
  474. dY_ = (double) Random::random();
  475. len = sqrt( (dX_ * dX_) + (dY_ * dY_) );
  476. dX_ /= len;
  477. dY_ /= len;
  478. dZ_ = 0.0; // we're not flying...
  479. /*
  480.  * Determine the sign of each component of the
  481.  * direction vector.
  482.  */
  483. if (X_ > (T_->upperX() - 2*T_->resol())) {
  484. if (dX_ > 0) 
  485. dX_ = -dX_;
  486. } else if (X_ < (T_->lowerX() + 2*T_->resol())) {
  487. if (dX_ < 0) 
  488. dX_ = -dX_;
  489. } else if (Random::uniform() <= 0.5) {
  490. dX_ = -dX_;
  491. }
  492. if (Y_ > (T_->upperY() - 2*T_->resol())) {
  493. if (dY_ > 0) 
  494. dY_ = -dY_;
  495. } else if (Y_ < (T_->lowerY() + 2*T_->resol())) {
  496. if (dY_ < 0) 
  497. dY_ = -dY_;
  498. } else if(Random::uniform() <= 0.5) {
  499. dY_ = -dY_;
  500. }
  501. #if 0
  502. fprintf(stderr, "Location: (%f, %f), Direction: (%f, %f)n",
  503. X_, Y_, dX_, dY_);
  504. #endif
  505. }
  506. void
  507. MobileNode::random_speed()
  508. {
  509. speed_ = Random::uniform() * MAX_SPEED;
  510. }
  511. double
  512. MobileNode::distance(MobileNode *m)
  513. {
  514. update_position(); // update my position
  515. m->update_position(); // update m's position
  516.         double Xpos = (X_ - m->X_) * (X_ - m->X_);
  517.         double Ypos = (Y_ - m->Y_) * (Y_ - m->Y_);
  518. double Zpos = (Z_ - m->Z_) * (Z_ - m->Z_);
  519.         return sqrt(Xpos + Ypos + Zpos);
  520. }
  521. double
  522. MobileNode::propdelay(MobileNode *m)
  523. {
  524. return distance(m) / SPEED_OF_LIGHT;
  525. }
  526. void 
  527. MobileNode::idle_energy_patch(float /*total*/, float /*P_idle*/)
  528. {
  529. }