Wiselib
|
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