Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib 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 Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ***************************************************************************/ 00019 #ifndef __ALGORITHMS_END_TO_END_COMMUNICATION_END_TO_END_COMMUNICATION_H__H__ 00020 #define __ALGORITHMS_END_TO_END_COMMUNICATION_END_TO_END_COMMUNICATION_H__H__ 00021 00022 #include "algorithms/end_to_end_communication_NoHGW/end_to_end_communication_msg.h" 00023 #include "algorithms/neighbor_discovery/echo.h" 00024 #include "algorithms/neighbor_discovery/pgb_payloads_ids.h" 00025 00026 #include "algorithms/cluster/clustering_types.h" 00027 #include "util/pstl/vector_static.h" 00028 #include "util/pstl/priority_queue.h" 00029 #include "util/pstl/pair.h" 00030 #include "util/pstl/map_static_vector.h" 00031 #include "internal_interface/routing_table/routing_table_static_array.h" 00032 #include "util/delegates/delegate.hpp" 00033 00034 #include "algorithms/cluster/fronts/fronts_core.h" 00035 #include "algorithms/cluster/modules/chd/attr_chd.h" 00036 #include "algorithms/cluster/modules/it/fronts_it.h" 00037 #include "algorithms/cluster/modules/jd/bfs_jd.h" 00038 00039 #include "util/serialization/serialization.h" 00040 #include "util/base_classes/routing_base.h" 00041 00042 //#define DEBUG 00043 //#define CTI_VISOR 00044 //#define USE_HIGHWAY 00045 00046 namespace wiselib { 00047 00051 template<typename OsModel_P, 00052 typename Radio_P, 00053 typename Neighbor_Discovery_P = wiselib::Echo<OsModel_P, Radio_P, typename OsModel_P::Timer, typename OsModel_P::Debug>, 00054 typename Cluster_P = wiselib::FrontsCore<OsModel_P, Radio_P, wiselib::AtributeClusterHeadDecision<OsModel_P, Radio_P>, wiselib::BfsJoinDecision<OsModel_P, Radio_P>, wiselib::FrontsIterator<OsModel_P, Radio_P> > > 00055 class EndToEndCommunication : public RoutingBase<OsModel_P, Radio_P> { 00056 public: 00057 00058 typedef OsModel_P OsModel; 00059 00060 typedef Radio_P Radio; 00061 typedef typename OsModel_P::Debug Debug; 00062 typedef typename OsModel_P::Clock Clock; 00063 typedef typename OsModel::Timer Timer; 00064 00065 typedef typename Radio::node_id_t node_id_t; 00066 typedef typename Radio::size_t size_t; 00067 typedef typename Radio::block_data_t block_data_t; 00068 typedef typename Radio::message_id_t message_id_t; 00069 typedef typename Timer::millis_t millis_t; 00070 00071 typedef Cluster_P Cluster; 00072 typedef Neighbor_Discovery_P NeighborDiscovery; 00073 00074 00075 typedef wiselib::AtributeClusterHeadDecision<OsModel, Radio> CHD_t; 00076 typedef wiselib::BfsJoinDecision<OsModel, Radio> JD_t; 00077 typedef wiselib::FrontsIterator<OsModel, Radio> IT_t; 00078 typedef wiselib::FrontsCore<OsModel, Radio, CHD_t, JD_t, IT_t> clustering_algo_t; 00079 typedef wiselib::StaticArrayRoutingTable<OsModel, Radio, 10> RoutingTable; 00080 typedef wiselib::Echo<OsModel, Radio, Timer, Debug> nb_t; 00081 00082 typedef wiselib::CommunicationMessage<OsModel, Radio> CommunicationMsg_t; 00083 typedef EndToEndCommunication<OsModel, Radio, NeighborDiscovery, Cluster> self_type; 00084 00085 typedef self_type* self_pointer_t; 00086 typedef delegate3<void, node_id_t, size_t, block_data_t*> endToEnd_delegate_t; 00087 00088 typedef CommunicationMessage<OsModel, Radio> Communicationmsg_t; 00089 00090 // -------------------------------------------------------------------- 00091 enum SpecialNodeIds { 00092 BROADCAST_ADDRESS = Radio::BROADCAST_ADDRESS, 00093 NULL_NODE_ID = Radio::NULL_NODE_ID 00094 }; 00095 // -------------------------------------------------------------------- 00096 enum Restrictions { 00097 MESSAGE_SIZE = Communicationmsg_t::MAX_PAYLOAD_LENGTH 00098 }; 00099 enum{ 00100 END_TO_END_MESSAGE = 245, 00101 NODE_IN_CLUSTER = 246, 00102 }; 00103 00104 enum ErrorCodes{ 00105 SUCCESS = OsModel::SUCCESS, 00106 ERR_UNSPEC = OsModel::ERR_UNSPEC 00107 }; 00108 // -------------------------------------------------------------------- 00109 00110 EndToEndCommunication() {} 00111 ~EndToEndCommunication() {} 00112 00113 void enable_radio(); 00114 void disable_radio(); 00115 00116 void send( node_id_t receiver, size_t len, block_data_t *data ); 00117 void on_receive (node_id_t from, size_t len, block_data_t *data ); 00118 00119 bool is_in_cluster ( node_id_t nodeID ); 00120 void print_statistics(); 00121 00122 int init( Radio& tx_radio, Timer& timer, Clock& clock, Debug& debug, Cluster& cluster, NeighborDiscovery& neighbor ); 00123 00124 template<class T, void (T::*TMethod)(node_id_t, size_t, block_data_t*)> 00125 uint8_t endToEnd_reg_recv_callback(T *obj_pnt) { 00126 endToEnd_recv_callback_ = endToEnd_delegate_t::template from_method<T, TMethod > ( obj_pnt ); 00127 return 0; 00128 } 00129 00130 void unreg_endToEnd_recv_callback() { 00131 endToEnd_recv_callback_ = endToEnd_delegate_t(); 00132 } 00133 00134 typename Radio::node_id_t id() 00135 { 00136 return tx_radio_->id(); 00137 } 00138 00139 void destruct() {} 00140 00141 00142 protected: 00143 typename Radio::self_pointer_t tx_radio_; 00144 typename Debug::self_pointer_t debug_; 00145 typename Clock::self_pointer_t clock_; 00146 00147 typename Timer::self_pointer_t timer_; 00148 typename Cluster::self_type* cluster_; 00149 typename NeighborDiscovery::self_t* neighbor_; 00150 00151 00152 CommunicationMsg_t comm_message; 00153 endToEnd_delegate_t endToEnd_recv_callback_; 00154 CHD_t CHD_; 00155 JD_t JD_; 00156 IT_t IT_; 00157 // METRICS FOR END_TO_END COMMUNICATION 00158 00159 millis_t disconnected_node_timeout_; 00160 int RX_total ; //Messages received from neighbor nodes 00161 //Metrics for cluster heads 00162 00163 uint16_t RX_childs; //Messages received from nodes in the cluster 00164 00165 uint16_t FW_childs; //Messages coming from nodes in the cluster and delivered to the final destination INSIDE THE SAME CLUSTER 00166 00167 00168 uint16_t TX_neigh; //Messages generated and transmitted directly to the final destination (Cluster heads uses the same metric for messages generated by itself) 00169 uint16_t TX_cluster_head; //Messages generated and transmitted to the cluster head because the node is not a direct neighbor 00170 uint16_t TX_in_cluster; 00171 00172 bool has_roomba_neighbor; 00173 node_id_t roomba_id; 00174 bool has_msg; 00175 00176 00177 int radio_recv_callback_id_; 00178 bool is_disconnected_node; 00179 00180 Radio& radio() 00181 { 00182 return *tx_radio_; 00183 } 00184 Timer& timer() 00185 { 00186 return *timer_; 00187 } 00188 Debug& debug() 00189 { 00190 return *debug_; 00191 } 00192 00193 Cluster& cluster() 00194 { 00195 return *cluster_; 00196 } 00197 00198 Clock& clock() 00199 { 00200 return *clock_; 00201 } 00202 00203 NeighborDiscovery& neighbor_discovery(){ 00204 return *neighbor_; 00205 } 00206 00207 }; 00208 00209 // ----------------------------------------------------------------------- 00210 00211 template<typename OsModel_P, 00212 typename Radio_P, 00213 typename Neighbor_Discovery_P, 00214 typename Cluster_P> 00215 int 00216 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P,Cluster_P>:: 00217 init (Radio& tx_radio, Timer& timer, Clock& clock, Debug& debug, Cluster& cluster, NeighborDiscovery& neighbor) {//HighwayCluster& highwaycluster, 00218 tx_radio_ = &tx_radio; 00219 timer_ = &timer; 00220 clock_ = &clock; 00221 neighbor_ = &neighbor; 00222 debug_ = &debug; 00223 cluster_= &cluster; 00224 RX_total = 0 ; //Messages received from neighbor nodes 00225 RX_childs = 0 ; 00226 FW_childs = 0; 00227 disconnected_node_timeout_ = (millis_t)1000; 00228 roomba_id = 0; 00229 TX_neigh = 0 ; 00230 TX_cluster_head = 0 ; 00231 00232 00233 cluster_->set_cluster_head_decision( CHD_ ); 00234 cluster_->set_join_decision( JD_ ); 00235 cluster_->set_iterator( IT_ ); 00236 cluster_->init( *tx_radio_, *timer_, *debug_, *neighbor_ ); 00237 cluster_->set_maxhops( 1 ); 00238 00239 #ifdef DEBUG 00240 debug_->debug("EndToEnd Algorithm: Successfully initialized module\n"); 00241 debug_->debug("Debug_->debug: Node %x: TX_neigh value is %i\n" , radio().id(), TX_neigh); 00242 #endif 00243 return SUCCESS; 00244 } 00245 00246 00247 template<typename OsModel_P, 00248 typename Radio_P, 00249 typename Neighbor_Discovery_P, 00250 typename Cluster_P> 00251 void 00252 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00253 enable_radio() 00254 { 00255 #ifdef DEBUG 00256 debug_->debug("EndToEndCommunication boots on %x\n", tx_radio_->id()); 00257 #endif 00258 00259 radio().enable_radio(); 00260 neighbor_discovery().enable(); 00261 00262 00263 radio_recv_callback_id_ = radio().template reg_recv_callback<self_type, &self_type::on_receive >(this); 00264 #ifdef DEBUG 00265 if( neighbor_discovery().register_payload_space( MOBILITY ) ) 00266 debug_->debug( "Could not register payload space in neighbor discovery module!\n" ); 00267 #endif 00268 00269 //Sets the nodes MOBILITY-payload to 0 (i.e. not a robot). 00270 uint8_t data = 0; 00271 neighbor_discovery().set_payload( MOBILITY, &data, sizeof( data ) ); 00272 00273 //Registers callback for the MOBILITY-payload 00274 uint8_t flags = nb_t::NEW_PAYLOAD_BIDI; 00275 // neighbor_discovery().template reg_event_callback<self_type, &self_type::arriving_robot>( MOBILITY, flags, this ); 00276 // has_roomba_neighbor = false; 00277 } 00278 00279 // ----------------------------------------------------------------------- 00280 00281 template<typename OsModel_P, 00282 typename Radio_P, 00283 typename Neighbor_Discovery_P, 00284 typename Cluster_P> 00285 void 00286 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00287 disable_radio(void) { 00288 #ifdef DEBUG 00289 debug_->debug("Called EndToEndCommunication::disable\n"); 00290 #endif 00291 //Unregister callbacks 00292 neighbor_discovery->unregister_payload_space( MOBILITY ); 00293 neighbor_discovery->unreg_recv_callback( MOBILITY ); 00294 radio().unregister_recv_callback( radio_recv_callback_id_ ); 00295 00296 neighbor_discovery->disable(); 00297 radio().disable_radio(); 00298 } 00299 00300 // ----------------------------------------------------------------------- 00301 00302 template<typename OsModel_P, 00303 typename Radio_P, 00304 typename Neighbor_Discovery_P, 00305 typename Cluster_P> 00306 void 00307 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00308 send( node_id_t destination, size_t len, block_data_t *data ) { 00309 00310 CommunicationMsg_t* msg = (CommunicationMsg_t*)data; 00311 #ifdef DEBUG 00312 debug().debug("Node %x is not a cluster leader\n", radio().id()); 00313 #endif 00314 00315 if (neighbor_discovery().is_neighbor_bidi(msg->dest())){ 00316 TX_neigh++; 00317 #ifdef DEBUG 00318 debug_->debug ("Node %x is a bidi neighbor of %x; sending message; sent a total of %i messages\n", msg->dest(), radio().id(), TX_neigh ); 00319 debug_->debug("Node %x: TX_neigh value is %i\n" , radio().id(), TX_neigh); 00320 #endif 00321 radio().send(msg->dest(), len , data); 00322 } 00323 00324 else if ((!neighbor_discovery().is_neighbor_bidi(msg->dest())) && (!cluster().is_cluster_head())){ 00325 TX_cluster_head++; 00326 #ifdef DEBUG 00327 debug_->debug ("Node %x: sending message to cluster leader %x\n", tx_radio_->id(), cluster().parent() ); 00328 debug().debug("Node %x: TX_cluster_head = %i\n", radio().id(), TX_cluster_head); 00329 #endif 00330 //comm_message.set_dest(cluster().parent()); 00331 radio().send( cluster().parent(), len, data ); 00332 } 00333 00334 else if (cluster().is_cluster_head()){ 00335 if (is_in_cluster(destination)) { 00336 TX_in_cluster++; 00337 radio().send( destination, len, data); 00338 } 00339 // else 00340 00341 // send_highway( destination, len, data ); 00342 00343 } 00344 } 00345 00346 /* template<typename OsModel_P, 00347 typename Radio_P, 00348 typename Neighbor_Discovery_P, 00349 typename Cluster_P> 00350 void 00351 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00352 send_highway( node_id_t destination, size_t len, block_data_t *data ) { 00353 00354 Node_vect neigh; 00355 highway().cluster_neighbors(&neigh); 00356 Node_vect_it it; 00357 //Broadcast the message toward all the other neighbor leaders 00358 00359 for( it = neigh.begin(); it != neigh.end(); ++it ) 00360 { 00361 #ifdef DEBUG 00362 debug_->debug("Neighbor Leaders of %x <--> %x\n", tx_radio_->id(), *it ); 00363 debug_->debug("Node %x Sending through the highway to all its neighboring clusters\n", tx_radio_->id()); 00364 #endif 00365 highway().send(*it, sizeof(data), data); 00366 } 00367 00368 // Start the timer to wait for an ACK saying if the node is connected to some cluster// 00369 00370 timer().template set_timer< self_type, &self_type::disconnected_node_timeout >( disconnected_node_timeout_ , this, (void *) 0 ); 00371 is_disconnected_node = true; 00372 }*/ 00373 00374 00375 template<typename OsModel_P, 00376 typename Radio_P, 00377 typename Neighbor_Discovery_P, 00378 typename Cluster_P> 00379 00380 void 00381 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00382 on_receive( node_id_t from, size_t len, block_data_t *data ) { 00383 message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data ); 00384 00385 00386 //Only treat CommunicationMessages 00387 if( msg_id == END_TO_END_MESSAGE ) 00388 { 00389 CommunicationMsg_t* msg = (CommunicationMsg_t*)data; 00390 00391 if( msg->dest() == tx_radio_->id() ) { 00392 // The message reached its destination => Notify registered receivers. 00393 notify_receivers( msg->source(), msg->payload_size(), msg->payload() ); 00394 #ifdef DEBUG 00395 debug_->debug("Node %x received an EndToEnd message from %x for itself\n", radio().id(), from); 00396 debug().debug("Node %x: Total RX messages = %i\n", radio().id(), RX_total); 00397 #endif 00398 #ifdef CTI_VISOR 00399 if ( from == cluster().parent()) 00400 debug_->debug("E2E_MSG; CLUST; %d; %d", radio().id(), from); 00401 else 00402 debug_->debug("E2E_MSG; NEIGH; %d; %d", radio().id(), from); 00403 #endif 00404 RX_total++; 00405 } 00406 00407 else if (cluster().is_cluster_head()){ 00408 #ifdef DEBUG 00409 debug().debug("Cluster leader %x received a message from %x destined to %x\n", radio().id(), from, msg->dest()); 00410 #endif 00411 RX_childs++; 00412 if (is_in_cluster( msg->dest()) || (neighbor_discovery().is_neighbor_bidi(msg->dest()))) { 00413 radio().send( msg->dest(), len, data ); 00414 FW_childs++; 00415 #ifdef DEBUG 00416 debug().debug("Node %x: Cluster leader forwarded a message for the destination %x \n",radio().id(), msg->dest()); 00417 #endif 00418 } 00419 00420 /* else { 00421 send_highway( from, len, data ); 00422 }*/ 00423 } 00424 } 00425 } 00426 00427 /*template<typename OsModel_P, 00428 typename Radio_P, 00429 typename Neighbor_Discovery_P, 00430 typename Cluster_P> 00431 void 00432 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00433 receive_highway(node_id_t from, size_t len, block_data_t *data){ 00434 message_id_t msg_id = read<OsModel, block_data_t, message_id_t>( data ); 00435 00436 CommunicationMsg_t* msg = (CommunicationMsg_t*)data; 00437 00438 if (msg_id == END_TO_END_MESSAGE){ 00439 #ifdef DEBUG 00440 debug_->debug("Node %x: Receiving message from the highway\n",radio().id()); 00441 #endif 00442 if (is_in_cluster(msg->dest())){ 00443 radio().send(msg->dest(), sizeof(data), data); 00444 #ifdef DEBUG 00445 debug().debug("Node %x: Delivering message to final destination %x\n", tx_radio_->id(), data[1]); 00446 #endif 00447 //Send back an answer to the leader from which we received the message 00448 CommunicationMsg_t ack; 00449 00450 This buffer is used as follows: 00451 buf[0] = MSG_TYPE 00452 buf[1] = a boolean flag: 1 means the desired node was found in the cluster, 0 means it was not found 00453 00454 ack.set_dest(from); 00455 ack.set_msg_id(NODE_IN_CLUSTER); 00456 uint8_t buf_to_send[8]; 00457 ack.set_payload(sizeof(buf_to_send), buf_to_send); 00458 highway().send(from, ack.buffer_size(),(uint8_t *) &ack); 00459 00460 } 00461 else 00462 debug().debug("Node %x: node is not in my cluster\n",radio().id()); 00463 } 00464 else if (msg_id == NODE_IN_CLUSTER){ 00465 debug().debug("Node %x: Receive a NODE_IN_CLUSTER message from highway\n", radio().id()); 00466 } 00467 }*/ 00468 00469 template<typename OsModel_P, 00470 typename Radio_P, 00471 typename Neighbor_Discovery_P, 00472 typename Cluster_P> 00473 bool 00474 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00475 is_in_cluster ( node_id_t nodeID ){ 00476 node_id_t cluster_members[cluster().childs_count()]; 00477 bool result = false; 00478 cluster().childs(cluster_members); 00479 for (int i = 0; i < cluster().childs_count(); i++){ 00480 if ( cluster_members[i] == nodeID ){ 00481 result = true; 00482 #ifdef DEBUG 00483 debug().debug("Node %x: node %x is in my cluster!\n", radio().id(), nodeID); 00484 #endif 00485 return result; 00486 } 00487 } 00488 #ifdef DEBUG 00489 debug().debug("Node %x: node %x is not in my cluster!\n", radio().id(), nodeID); 00490 #endif 00491 return result; 00492 } 00493 00494 /*template<typename OsModel_P, 00495 typename Radio_P, 00496 typename Neighbor_Discovery_P, 00497 typename Cluster_P> 00498 void 00499 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00500 disconnected_node_timeout ( void* a ){ 00501 if (is_disconnected_node){ 00502 #ifdef DEBUG 00503 debug_->debug("Node %x: Send to Robot\n", radio().id()); 00504 #endif 00505 //int dummyDest = 0; 00506 //send_to_robot( dummyDest ); 00507 } 00508 #ifdef DEBUG 00509 else 00510 debug_->debug("Node %x: destination node was in my cluster. Message delivered\n", radio().id()); 00511 #endif 00512 }*/ 00513 00514 /*template<typename OsModel_P, 00515 typename Radio_P, 00516 typename Neighbor_Discovery_P, 00517 typename Cluster_P> 00518 void EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00519 arriving_robot( uint8_t event, node_id_t from, uint8_t len, uint8_t* data ) { 00520 if( ( event & nb_t::NEW_PAYLOAD_BIDI ) != 0 ) 00521 { 00522 if( *data ) 00523 { 00524 has_roomba_neighbor = true; 00525 roomba_id = from; 00526 00527 if( has_msg ) 00528 { 00529 // send_message(); 00530 } 00531 } 00532 } 00533 }*/ 00534 00535 template<typename OsModel_P, 00536 typename Radio_P, 00537 typename Neighbor_Discovery_P, 00538 typename Cluster_P> 00539 void 00540 EndToEndCommunication<OsModel_P, Radio_P, Neighbor_Discovery_P, Cluster_P>:: 00541 print_statistics (){ 00542 debug().debug("PRINTING METRICS OF NODE %x\n", radio().id()); 00543 debug().debug("RX_total = %i\n; RX_childs = %i\n; FW_childs = %i\n; TX_neigh = %i\n; TX_cluster_head = %i\n", 00544 RX_total, RX_childs, FW_childs, TX_neigh, TX_cluster_head); 00545 } 00546 } 00547 #endif 00548 00549 00550 00551 00552 00553 00554 00555 00556 00557 00558 00559 00560 00561 00562 00563 00564 00565 00566 00567 00568 00569 00570 00571