RandomWaypointNode.cc

00001 // Copyright 2008 Michael Marsh, University of Maryland.
00002 //
00003 // This file is part of pydtn.
00004 //
00005 // pydtn is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // pydtn is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with pydtn.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // The views and conclusions contained in the software and documentation
00019 // are those of the authors and should not be interpreted as representing
00020 // official policies, either expressed or implied, of the University
00021 // of Maryland.
00022 //
00023 // pydtn extends and embeds the Python interpreter, which is
00024 // Copyright 2001-2006 Python Software Foundation, All Rights Reserved,
00025 // and is released under the PSF License Agreement.
00026 //
00027 // RANLUX random number generation uses the Boost library,
00028 // Copyright 1994-2006 by various authors (details in individual files),
00029 // which is released under the Boost Software License, Version 1.0.
00030 
00031 #include "simlpy/interpreter_defs.h"
00032 #include "simlpy/interpreter_hooks.h"
00033 
00034 #include "RandomWaypointNode.h"
00035 #include "WaypointRange.h"
00036 #include "RectangularAlignedWaypointRange.h"
00037 #include "ParallelogramWaypointRange.h"
00038 #include "simlpy/Clock.h"
00039 #include "simlpy/SimulationException.h"
00040 
00041 #include <iostream>
00042 #include <stdlib.h>
00043 
00044 using namespace Mobility;
00045 
00046 const std::string
00047 RandomWaypointNode::kIdentifier( "node:mobile:random_waypoint" );
00048 
00049 RandomWaypointNode::RandomWaypointNode() :
00050    m_range( 0 ),
00051    m_speedMin( 0.001 ),      // a typical pace for an adult snail
00052    m_speedMax( 299792458.0 ) // c
00053 {
00054 }
00055 
00056 RandomWaypointNode::~RandomWaypointNode()
00057 {
00058    if ( 0 != m_range ) delete m_range;
00059 }
00060 
00061 Entity*
00062 RandomWaypointNode::create() const
00063 {
00064    RandomWaypointNode* n = new RandomWaypointNode;
00065    n->trigger();
00066    return n;
00067 }
00068 
00069 void
00070 RandomWaypointNode::configure( const ArgList& args )
00071 {
00072    unsigned int nargs = args.size();
00073    if ( 0 == nargs )
00074    {
00075       std::cerr << "no arguments passed to config()" << std::endl;
00076       throw SimulationException( __FILE__ , __LINE__ );
00077    }
00078    std::string command = parse_string(args[0]);
00079    if ( "range" == command )
00080    {
00081       // We're going to use Duck Typing here.
00082       if ( nargs < 3 )
00083       {
00084          std::cerr << "config('range') requires at least two arguments"
00085                    << std::endl;
00086          throw SimulationException( __FILE__ , __LINE__ );
00087       }
00088       if ( 3 == nargs )
00089       {
00090          // Is it a rectangular region aligned with the axes?
00091          try
00092          {
00093             Position ll = parse_position( args[1] );
00094             Position ur = parse_position( args[2] );
00095             if ( 0 != m_range ) delete m_range;
00096             m_range = new RectangularAlignedWaypointRange( ll, ur );
00097             return;
00098          }
00099          catch ( ... )
00100          {
00101          }
00102       }
00103       if ( 4 == nargs )
00104       {
00105          // Is it a 2-d parallelogram?
00106          try
00107          {
00108             Position a = parse_position( args[1] );
00109             Position b = parse_position( args[2] );
00110             Position c = parse_position( args[3] );
00111             if ( 0 != m_range ) delete m_range;
00112             m_range = new ParallelogramWaypointRange( a, b, c, a );
00113             return;
00114          }
00115          catch ( ... )
00116          {
00117          }
00118       }
00119       if ( 5 == nargs )
00120       {
00121          // Is it a 3-d parallelohedron?
00122          try
00123          {
00124             Position a = parse_position( args[1] );
00125             Position b = parse_position( args[2] );
00126             Position c = parse_position( args[3] );
00127             Position d = parse_position( args[4] );
00128             if ( 0 != m_range ) delete m_range;
00129             m_range = new ParallelogramWaypointRange( a, b, c, d );
00130             return;
00131          }
00132          catch ( ... )
00133          {
00134          }
00135       }
00136       std::cerr << "Could not understand argument list" << std::endl;
00137       throw SimulationException( __FILE__ , __LINE__ );
00138    }
00139    if ( "speed" == command )
00140    {
00141       if ( nargs < 2 )
00142       {
00143          std::cerr << "config('speed') requires at least one speed"
00144                    << std::endl;
00145          throw SimulationException( __FILE__ , __LINE__ );
00146       }
00147       double minSpeed = parse_double( args[1] );
00148       double maxSpeed = minSpeed;
00149       if ( nargs > 2 )
00150       {
00151          maxSpeed = parse_double( args[2] );
00152       }
00153       setSpeed( minSpeed, maxSpeed );
00154       return;
00155    }
00156    MobileNode::configure(args);
00157 }
00158 
00159 void
00160 RandomWaypointNode::emit( const ArgList& args )
00161 {
00162    MobileNode::emit(args);
00163 }
00164 
00165 InterpreterItem
00166 RandomWaypointNode::get( const ArgList& args )
00167 {
00168    unsigned int nargs = args.size();
00169    if ( 0 == nargs )
00170    {
00171       std::cerr << "No attribute specified" << std::endl;
00172       throw SimulationException( __FILE__ , __LINE__ );
00173    }
00174 
00175    std::string attr = parse_string(args[0]);
00176 
00177    if ( "speed_range" == attr )
00178    {
00179       ArgList alist;
00180       alist.push_back( construct_double( m_speedMin ) );
00181       alist.push_back( construct_double( m_speedMax ) );
00182       return construct_list( alist );
00183    }
00184 
00185    return MobileNode::get(args);
00186 }
00187 
00188 bool
00189 RandomWaypointNode::handler( WaypointEvent& event )
00190 {
00191    setWaypoint( event.waypoint() );
00192    return true;
00193 }
00194 
00195 void
00196 RandomWaypointNode::setWaypoint( const Presence& wp )
00197 {
00198    if ( 0 != m_range )
00199    {
00200       Position p = m_range->next( wp.position() );
00201       Position delta = p - wp.position();
00202       double dist = delta.length();
00203       double speed = m_speedMin +
00204          ( m_speedMax - m_speedMin ) * prng();
00205       double dt = dist / speed;
00206       long int dts = (long int) ::floor(dt);
00207       long int dtus = (long int)( Time::MILLION * ( dt - ::floor(dt) ) );
00208       Time t( dts, dtus );
00209       t += wp.time();
00210       t += wp.duration();
00211       Clock::tentative( new WaypointEvent(this,
00212                                           this,
00213                                           wp.time(),
00214                                           Presence(t,p,Time())) );
00215    }
00216    MobileNode::setWaypoint(wp);
00217 }
00218 
00219 void
00220 RandomWaypointNode::setRange( WaypointRange* r )
00221 {
00222    if ( 0 != r )
00223    {
00224       if ( 0 != m_range ) delete m_range;
00225       m_range = r;
00226    }
00227 }
00228 
00229 void
00230 RandomWaypointNode::setSpeed( double min_speed, double max_speed )
00231 {
00232    if ( max_speed < min_speed )
00233    {
00234       std::cerr
00235          << "The node maximum speed must be at least the node minimum speed."
00236          << std::endl;
00237       throw SimulationException( __FILE__ , __LINE__ );
00238    }
00239    if ( min_speed <= 0 )
00240    {
00241       std::cerr << "The node minimum speed must be greater than zero."
00242                 << std::endl;
00243    }
00244    m_speedMin = min_speed;
00245    m_speedMax = max_speed;
00246 }

Generated on Mon Mar 24 11:15:46 2008 for Pydtn Simulator by  doxygen 1.5.4