Wiselib
wiselib.testing/algorithms/end_to_end_communication_NoHGW/end_to_end_communication_NoHGW.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines