Wiselib
wiselib.testing/algorithms/roomba_message_delivery/roomba_movement.h
Go to the documentation of this file.
00001 #ifndef __ROOMBA_MOVEMENT_H__
00002 #define __ROOMBA_MOVEMENT_H__
00003 
00004 #include <stdint.h>
00005 
00006 #include "util/standalone_math.h"
00007 #include "util/serialization/serialization.h"
00008 
00009 #include "external_interface/external_interface.h"
00010 
00011 #include "external_interface/pc/roomba.h"
00012 #include "external_interface/pc/roomba_motion.h"
00013 #include "external_interface/pc/roomba_event_sensor.h"
00014 
00015 #include "algorithms/roomba_message_delivery/roomba_movement_message.h"
00016 
00017 template<   typename OsModel_P,
00018       typename Roomba_P,
00019       typename Radio_P = typename OsModel_P::Radio,
00020       typename Debug_P = typename OsModel_P::Debug,
00021       typename Clock_P = typename OsModel_P::Clock,
00022       typename Timer_P = typename OsModel_P::Timer,
00023       typename Rand_P = typename OsModel_P::Rand
00024       >
00025 class RoombaMovement {
00026 public:
00027    typedef OsModel_P Os;
00028    typedef Roomba_P Roomba;
00029    typedef Radio_P Radio;
00030    typedef Debug_P Debug;
00031    typedef Clock_P Clock;
00032    typedef Timer_P Timer;
00033    typedef Rand_P Rand;
00034 
00035    typedef RoombaMovement<Os, Roomba, Radio, Debug, Clock, Timer, Rand> self_type;
00036    typedef self_type* self_pointer_t;
00037 
00038    typedef typename RoombaMovementMessage<Os, Radio>::self_type msg_t;
00039    typedef wiselib::RoombaMotion<Roomba, typename Roomba::Math> RoombaMotion;
00040    typedef wiselib::RoombaEventSensor<Os, Roomba> RoombaEventSensor;
00041 
00042    typedef typename Radio::block_data_t block_data_t;
00043    typedef typename Radio::size_t size_t;
00044    typedef typename Radio::node_id_t node_id_t;
00045    typedef typename Radio::message_id_t message_id_t;
00046 
00047    enum MovementPattern {
00048       RANDOM_WALK,
00049       LINE
00050    };
00051 
00052    static const uint32_t
00053       RANDOM_WALK_MIN_MOVE = 3000,
00054       RANDOM_WALK_MAX_MOVE = 8000,
00055       RANDOM_WALK_MIN_ROTATE = 1000,
00056       RANDOM_WALK_MAX_ROTATE = 3000;
00057 
00058    void init( Roomba& roomba, Radio* radio, Debug& debug, Clock& clock, Timer& timer, Rand& rand ) {
00059       radio_ = radio;
00060       debug_ = &debug;
00061       timer_ = &timer;
00062       rand_ = &rand;
00063       clock_ = &clock;
00064       roomba_ = &roomba;
00065 
00066       roomba_motion_.init( *roomba_ );
00067       roomba_event_sensor_.init(*roomba_);
00068 
00069       init();
00070    }
00071 
00072 
00073    void init()
00074    {
00075       movement_pattern_ = RANDOM_WALK;
00076       rand_->srand( clock_->microseconds( clock_->time() ) );
00077 
00078       if( radio_ ) {
00079          radio_->enable_radio();
00080          radio_->template reg_recv_callback<self_type, &self_type::on_receive>( this  );
00081       }
00082 
00083       roomba_event_sensor_.template reg_event_callback<self_type, &self_type::on_event>( this );
00084 
00085       speed_ = 0;
00086       duration_ = 10000;
00087 
00088       stop();
00089    }
00090 
00091    void inline start( int16_t speed = 300 )
00092    {
00093       if( is_stopped() )
00094       {
00095          speed_ = speed;
00096          stopped_ = false;
00097          next_action_ = MOVE;
00098          perform_action();
00099       }
00100    }
00101 
00102    void inline stop()
00103    {
00104       stop_movement();
00105       stopped_ = true;
00106    }
00107 
00108    bool inline is_stopped()
00109    {
00110       return stopped_;
00111    }
00112 
00113    void inline set_movement_pattern_to_line( uint32_t duration=10000 )
00114    {
00115       movement_pattern_ = LINE;
00116       duration_ = duration;
00117    }
00118 
00119    void inline set_movement_pattern_to_random_walk()
00120    {
00121       movement_pattern_ = RANDOM_WALK;
00122    }
00123 
00124 protected:
00125    enum ActionType {
00126       NONE = 0,
00127       MOVE,
00128       MOVE_BACKWARD,
00129       ROTATE,
00130       STOP,
00131    };
00132 
00133    void turn( int16_t speed ) {
00134       roomba_motion_.turn( speed );
00135    }
00136 
00137    void move_callback( void* userdata ) {
00138       if( cur_speed_ != dest_speed_ ) {
00139          if( dest_speed_ - cur_speed_ > 0 ) {
00140             cur_speed_ = ( cur_speed_ + 50 > dest_speed_ ) ? dest_speed_ : cur_speed_ + 50;
00141          } else {
00142             cur_speed_ = ( cur_speed_ - 50 < dest_speed_ ) ? dest_speed_ :cur_speed_ - 50;
00143          }
00144 
00145       // debug_->debug( "Changing speed to %d.\n", cur_speed_ );
00146          roomba_motion_.move( cur_speed_ );
00147 
00148          timer_->template set_timer<self_type, &self_type::move_callback>( 100, this, 0 );
00149       }
00150 
00151       if( cur_speed_ == dest_speed_ )
00152          changing_speed_ = false;
00153    }
00154       
00155       void distance() {
00156          return roomba_motion_.distance();
00157       }
00158 
00159    void move( int16_t speed ) {
00160       dest_speed_ = speed;
00161       changing_speed_ = true;
00162 
00163       move_callback( 0 );
00164    }
00165 
00166    void stop_movement() {
00167       roomba_motion_.move( 0 );
00168       cur_speed_ = 0;
00169       dest_speed_ = 0;
00170       changing_speed_ = false;
00171    }
00172 
00173    void perform_action()
00174    {
00175       if( !is_stopped() )
00176       {
00177          uint32_t duration;
00178          int8_t direction;
00179 
00180          if( movement_pattern_ == RANDOM_WALK )
00181          {
00182             switch( next_action_ )
00183             {
00184             case MOVE:
00185                duration = RANDOM_WALK_MIN_MOVE + uint32_t( double( (*rand_)() )/Rand::RANDOM_MAX*(RANDOM_WALK_MAX_MOVE-RANDOM_WALK_MIN_MOVE) );
00186                debug_->debug( "Moving for %ims.\n", duration );
00187                move( speed_ );
00188                next_action_ = STOP;
00189 
00190                break;
00191 
00192             case STOP:
00193                duration = 500;
00194                debug_->debug( "Stopping.\n", duration );
00195                move( 0 );
00196                next_action_ = ROTATE;
00197 
00198                break;
00199 
00200             case ROTATE:
00201                duration = RANDOM_WALK_MIN_ROTATE + uint32_t( double( (*rand_)() )/(Rand::RANDOM_MAX)*(RANDOM_WALK_MAX_ROTATE-RANDOM_WALK_MIN_ROTATE));
00202                debug_->debug( "Turning for %ims.\n", duration );
00203                direction = ( ( (*rand_)() <= Rand::RANDOM_MAX/2 ) ? 1 : -1 );
00204                turn( speed_ * direction );
00205                next_action_ = MOVE;
00206 
00207                break;
00208 
00209             default:
00210                debug_->debug( "Encountered unknown action. Stopped.\n" );
00211                stop();
00212             }
00213          } else {
00214             switch( next_action_ )
00215             {
00216             case MOVE:
00217                duration = duration_;
00218                debug_->debug( "Moving for %ims.\n", duration );
00219                move( speed_ );
00220                next_action_ = MOVE_BACKWARD;
00221                break;
00222 
00223             case MOVE_BACKWARD:
00224                duration = duration_;
00225                debug_->debug( "Moving backward for %ims.\n", duration );
00226                move( -speed_ );
00227                next_action_ = MOVE;
00228                break;
00229 
00230             default:
00231                debug_->debug( "Encountered unknown action. Stopped.\n" );
00232                stop();
00233             }
00234          }
00235 
00236          if( !is_stopped() ) {
00237             timer_->template set_timer<self_type, &self_type::on_timer>( duration, this, (void*)0 );
00238             debug_->debug( "-> Movement Timer was set\n" );
00239          }
00240       }
00241       else
00242       {
00243          stop();
00244       }
00245    }
00246 
00247    /*
00248     * Timer callback.
00249     */
00250    void on_timer( void* userdata ) {
00251       if( changing_speed_ )
00252       {
00253          timer_->template set_timer<self_type, &self_type::on_timer>( 500, this, (void*)0 );
00254       } else {
00255          perform_action();
00256       }
00257    }
00258 
00259    /*
00260     * Receive callback.
00261     *
00262     * Starts/stops movement on incoming start/stop-message.
00263     */
00264    void on_receive( node_id_t id, size_t size, block_data_t* data) {
00265       message_id_t msg_id = wiselib::read<Os, block_data_t, message_id_t>( data );
00266 
00267       if( msg_id == msg_t::ROOMBA_MOVEMENT_MESSAGE_ID )
00268       {
00269          msg_t* msg = (msg_t*)data;
00270 
00271          switch( msg->msg_type() )
00272          {
00273          case msg_t::STOP_MOVEMENT:
00274             debug_->debug( "Received stop\n");
00275             stop();
00276             break;
00277          case msg_t::START_MOVEMENT:
00278             debug_->debug( "Received start\n");
00279             start();
00280             break;
00281          default:
00282             debug_->debug( "Received RoombaMovementMessage with unknown type %d\n", msg->msg_type() );
00283          }
00284       }
00285    }
00286 
00287 
00288    void on_event( uint8_t event ) {
00289       if( event == RoombaEventSensor::EVENT_WALL )
00290       {
00291          int16_t distance = (int16_t) roomba_motion_.distance();
00292             debug_->debug( "Roomba hit wall! Moved distance is %d\n", distance );
00293             if( movement_pattern_ == RANDOM_WALK )
00294             {
00295                stop_movement();
00296                move( -speed_ );
00297                next_action_ = STOP;
00298             } else {
00299                stop();
00300             }
00301          }
00302       }
00303 
00304       Radio* radio_;
00305       Roomba* roomba_;
00306       RoombaMotion roomba_motion_;
00307       RoombaEventSensor roomba_event_sensor_;
00308       typename Debug::self_pointer_t debug_;
00309       typename Timer::self_pointer_t timer_;
00310       typename Rand::self_pointer_t rand_;
00311       typename Clock::self_pointer_t clock_;
00312 
00313       ActionType next_action_;
00314       bool stopped_;
00315       int16_t speed_;
00316       uint32_t duration_;
00317       MovementPattern movement_pattern_;
00318 
00319       int16_t cur_speed_;
00320       int16_t dest_speed_;
00321       bool changing_speed_;
00322 };
00323 
00324 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines