Wiselib
wiselib.testing/algorithms/localization/distance_based/modules/distance/localization_euclidean_module.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_LOCALIZATION_DISTANCE_BASED_LOCALIZATION_EUCLIEDEAN_MODULE_H
00020 #define __ALGORITHMS_LOCALIZATION_DISTANCE_BASED_LOCALIZATION_EUCLIEDEAN_MODULE_H
00021 
00022 #include "algorithms/localization/distance_based/modules/localization_module.h"
00023 #include "algorithms/localization/distance_based/modules/distance/localization_euclidean_messages.h"
00024 #include "algorithms/localization/distance_based/util/localization_defutils.h"
00025 #include "algorithms/localization/distance_based/math/localization_triangulation.h"
00026 #include "algorithms/localization/distance_based/math/localization_statistic.h"
00027 #include "config_testing.h"
00028 
00029 
00030 namespace wiselib
00031 {
00032 
00035    const char* EUCL_COL_CHECK_STD[] = { "lax", "strict", "one" };
00036    const char* EUCL_COL_CHECK_NV[] = { "lax", "strict", "one" };
00037    const char* EUCL_COL_CHECK_CN[] = { "lax", "strict", "one" };
00038    const char* EUCL_ALGO[] = { "normal", "opt" };
00039    const char* EUCL_VOTE[] = { "nv", "cn", "nvcn", "cnnv" };
00041 
00042 
00044 
00064    template<typename OsModel_P,
00065             typename Radio_P,
00066             typename Clock_P,
00067             typename Distance_P,
00068             typename Debug_P,
00069             typename SharedData_P,
00070             typename DistancePair_P>
00071    class LocalizationEuclideanModule
00072       : public LocalizationModule<OsModel_P, Radio_P, SharedData_P>
00073    {
00074 
00075    public:
00076       typedef OsModel_P OsModel;
00077       typedef Radio_P Radio;
00078       typedef Clock_P Clock;
00079       typedef Distance_P Distance;
00080       typedef Debug_P Debug;
00081       typedef SharedData_P SharedData;
00082       typedef DistancePair_P DistancePair;
00083 
00084       typedef LocalizationSumDistModule<OsModel, Radio, Clock, Distance, Debug, SharedData> self_type;
00085       typedef LocalizationModule<OsModel, Radio, SharedData> base_type;
00086 
00087       typedef typename Radio::size_t size_t;
00088       typedef typename Radio::node_id_t node_id_t;
00089       typedef typename Radio::block_data_t block_data_t;
00090 
00091       typedef typename Clock_P::time_t time_t;
00092 
00093       typedef typename SharedData::DistanceMap DistanceMap;
00094       typedef typename SharedData::NodeList NodeList;
00095       typedef typename NodeList::iterator NodeListIterator;
00096 
00097       typedef LocalizationEuclideanInitMessage<OsModel, Radio> EuclideanInitMessage;
00098       typedef LocalizationEuclideanAnchorMessage<OsModel, Radio> EuclideanAnchorMessage;
00099       typedef LocalizationEuclideanNeighborMessage<OsModel, Radio, DistanceMap> EuclideanNeighborMessage;
00100 
00101       typedef LocalizationStatistic<OsModel> Statistics;
00102 
00103       typedef typename SharedData::Neighborhood::NeighborhoodIterator NeighborhoodIterator;
00104 
00105       enum EuclideanCollinearCheckStd
00106       {
00107          eu_cc_std_lax,
00108          eu_cc_std_strict,
00109          eu_cc_std_none
00110       };
00111 
00112       enum EuclideanCollinearCheckNV
00113       {
00114          eu_cc_nv_lax,
00115          eu_cc_nv_strict,
00116          eu_cc_nv_none
00117       };
00118 
00119       enum EuclideanCollinearCheckCN
00120       {
00121          eu_cc_cn_lax,
00122          eu_cc_cn_strict,
00123          eu_cc_cn_none
00124       };
00125 
00126       enum EuclideanAlgo
00127       {
00128          eu_algo_normal,
00129          eu_algo_opt
00130       };
00131 
00132       enum EuclideanVote
00133       {
00134          eu_vote_nv,
00135          eu_vote_cn,
00136          eu_vote_nvcn,
00137          eu_vote_cnnv
00138       };
00139 
00143       LocalizationEuclideanModule();
00145       ~LocalizationEuclideanModule();
00147 
00148 
00151 
00155       void receive( node_id_t from, size_t len, block_data_t *data );
00161       void work( void );
00163 
00164 
00167 
00170       bool finished( void );
00172 
00173       void rollback( void );
00174 
00175 
00176       void init( Radio& radio, Clock& clock, Debug& debug, SharedData& shared_data, Distance& distance ) {
00177          radio_ = &radio;
00178          clock_ = &clock;
00179          debug_ = &debug;
00180          this->set_shared_data( shared_data );
00181          distance_ = &distance;
00182       }
00183 
00184    protected:
00185 
00188 
00193       bool process_euclidean_init_message( node_id_t from, size_t len, block_data_t *data );
00199       void broadcast_neighborhood( void );
00205       bool process_euclidean_neighbor_message( node_id_t from, size_t len, block_data_t *data );
00213       bool process_euclidean_anchor_message( node_id_t from, size_t len, block_data_t *data );
00219       void execute_euclidean( node_id_t anchor );
00221 
00222 
00225 
00236       double find_anchor_distance( node_id_t anchor );
00248       double find_anchor_distance_opt( node_id_t anchor );
00260       NodeList find_unique_neighbor_neighbors( node_id_t anchor, node_id_t n1, node_id_t n2 );
00272       NodeList find_common_neighbor_neighbors( node_id_t anchor, node_id_t n1, node_id_t n2 );
00287       NodeList find_common_neighbor_neighbors_opt( node_id_t, node_id_t, node_id_t, double& );
00319       double neighbor_vote(
00320             node_id_t, node_id_t, node_id_t,
00321             DistancePair&, NodeList& );
00339       double common_neighbor(
00340             node_id_t, node_id_t, node_id_t,
00341             DistancePair&, NodeList& );
00343 
00344 
00347 
00350       void set_collinear_check_std( EuclideanCollinearCheckStd check )
00351       { cc_std_ = check; }
00352       void set_collinear_check_nv( EuclideanCollinearCheckNV check )
00353       { cc_nv_ = check; }
00354       void set_collinear_check_cn( EuclideanCollinearCheckCN check )
00355       { cc_cn_ = check; }
00356       void set_euclidean_algo( EuclideanAlgo algo )
00357       { algo_ = algo; }
00358       void set_euclidean_algo( EuclideanVote vote )
00359       { vote_ = vote; }
00361 
00362 
00363    private:
00364 
00365       enum MessagesIds
00366       {
00367          EUCLIDEAN_INIT_MESSAGE = 203,
00368          EUCLIDEAN_ANCHOR_MESSAGE = 204,
00369          EUCLIDEAN_NEIGHBOR_MESSAGE = 205
00370       };
00371 
00372       enum EuclideanState
00373       {
00374          eu_init,
00375          eu_wait,
00376          eu_broadcast,
00377          eu_work,
00378          eu_finished
00379       };
00380 
00381       EuclideanState state_;
00382       EuclideanCollinearCheckStd cc_std_;
00383       EuclideanCollinearCheckNV cc_nv_;
00384       EuclideanCollinearCheckCN cc_cn_;
00385       EuclideanAlgo algo_;
00386       EuclideanVote vote_;
00387 
00388       time_t last_useful_msg_;
00389       double col_measure_;
00390 
00391       Radio* radio_;
00392       Clock* clock_;
00393       Debug* debug_;
00394       Distance* distance_;
00395    };
00396    // ----------------------------------------------------------------------
00397    // ----------------------------------------------------------------------
00398    // ----------------------------------------------------------------------
00399    template<typename OsModel_P,
00400             typename Radio_P,
00401             typename Clock_P,
00402             typename Distance_P,
00403             typename Debug_P,
00404             typename SharedData_P,
00405             typename DistancePair_P>
00406    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00407    LocalizationEuclideanModule()
00408       : state_            ( eu_init ),
00409          cc_std_          ( eu_cc_std_lax ),
00410          cc_nv_           ( eu_cc_nv_lax ),
00411          cc_cn_           ( eu_cc_cn_strict ),
00412          algo_            ( eu_algo_opt ),
00413          vote_            ( eu_vote_nvcn ),
00414          last_useful_msg_ ( 0 ),
00415          col_measure_     ( 0 )
00416    {}
00417    // ----------------------------------------------------------------------
00418    template<typename OsModel_P,
00419             typename Radio_P,
00420             typename Clock_P,
00421             typename Distance_P,
00422             typename Debug_P,
00423             typename SharedData_P,
00424             typename DistancePair_P>
00425    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00426    ~LocalizationEuclideanModule()
00427    {}
00428    // ----------------------------------------------------------------------
00429    template<typename OsModel_P,
00430             typename Radio_P,
00431             typename Clock_P,
00432             typename Distance_P,
00433             typename Debug_P,
00434             typename SharedData_P,
00435             typename DistancePair_P>
00436    void
00437    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00438    receive( node_id_t from, size_t len, block_data_t *data )
00439    {
00440       switch ( data[0] )
00441       {
00442          case EUCLIDEAN_INIT_MESSAGE:
00443             process_euclidean_init_message( from, len, data );
00444             break;
00445          case EUCLIDEAN_ANCHOR_MESSAGE:
00446             process_euclidean_anchor_message( from, len, data );
00447             break;
00448          case EUCLIDEAN_NEIGHBOR_MESSAGE:
00449             process_euclidean_neighbor_message( from, len, data );
00450             break;
00451       }
00452    }
00453    // ----------------------------------------------------------------------
00454    template<typename OsModel_P,
00455             typename Radio_P,
00456             typename Clock_P,
00457             typename Distance_P,
00458             typename Debug_P,
00459             typename SharedData_P,
00460             typename DistancePair_P>
00461    void
00462    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00463    work( void )
00464    {
00465       // send initial messages
00466       if ( state_ == eu_init )
00467       {
00468          if ( this->shared_data().is_anchor() )
00469          {
00470             EuclideanInitMessage message;
00471             message.set_msg_id( EUCLIDEAN_INIT_MESSAGE );
00472             message.set_anchor( true );
00473             message.set_source_position( this->shared_data().position() );
00474             radio_->send(  Radio::BROADCAST_ADDRESS,
00475                          message.buffer_size(), (block_data_t*)&message );
00476          }
00477          else
00478          {
00479             EuclideanInitMessage message;
00480             message.set_msg_id( EUCLIDEAN_INIT_MESSAGE );
00481             message.set_anchor( false );
00482             radio_->send( Radio::BROADCAST_ADDRESS,
00483                          message.buffer_size(), (block_data_t*)&message );
00484          }
00485 
00486          state_ = eu_wait;
00487       }
00488 
00489       // after idle-time passed, initial messages of neighbors had already been
00490       // received and state is set to 'broadcast'.
00491       if ( state_ == eu_wait &&
00492                clock_->time() - last_useful_msg_ >
00493                   this->shared_data().idle_time() )
00494          state_ = eu_broadcast;
00495 
00496       // broadcast collected information
00497       if ( state_ == eu_broadcast )
00498          broadcast_neighborhood();
00499    }
00500    // ----------------------------------------------------------------------
00501    template<typename OsModel_P,
00502             typename Radio_P,
00503             typename Clock_P,
00504             typename Distance_P,
00505             typename Debug_P,
00506             typename SharedData_P,
00507             typename DistancePair_P>
00508    bool
00509    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00510    finished( void )
00511    {
00512       return (state_ == eu_finished);
00513    }
00514    // ----------------------------------------------------------------------
00515    template<typename OsModel_P,
00516             typename Radio_P,
00517             typename Clock_P,
00518             typename Distance_P,
00519             typename Debug_P,
00520             typename SharedData_P,
00521             typename DistancePair_P>
00522    void
00523    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00524    rollback( void )
00525    {
00526       state_ = eu_init;
00527       last_useful_msg_ = clock_->time();
00528       col_measure_ = 0;
00529    }
00530    // ----------------------------------------------------------------------
00531    template<typename OsModel_P,
00532             typename Radio_P,
00533             typename Clock_P,
00534             typename Distance_P,
00535             typename Debug_P,
00536             typename SharedData_P,
00537             typename DistancePair_P>
00538    bool
00539    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00540    process_euclidean_init_message( node_id_t from, size_t len, block_data_t* data )
00541    {
00542       EuclideanInitMessage* msg = (EuclideanInitMessage*)data;
00543       Vec source_pos = msg->source_position();
00544       double distance = distance_->distance( from );
00545       if ( distance == UNKNOWN_DISTANCE )
00546          return false;
00547 
00548       last_useful_msg_ = clock_->time();
00549 
00550       // add info of received message to own neighborhood
00551       if ( msg->anchor() )
00552          this->neighborhood().update_anchor( from, source_pos, distance );
00553       else
00554          this->neighborhood().update_neighbor( from, distance );
00555 
00556      //BugFix: One-hop to anchor
00557      if ( this->neighborhood().valid_anchor_cnt() >= (int)this->shared_data().floodlimit() )
00558         state_ = eu_finished;
00559 
00560       return true;
00561    }
00562    // ----------------------------------------------------------------------
00563    template<typename OsModel_P,
00564             typename Radio_P,
00565             typename Clock_P,
00566             typename Distance_P,
00567             typename Debug_P,
00568             typename SharedData_P,
00569             typename DistancePair_P>
00570    void
00571    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00572    broadcast_neighborhood( void )
00573    {
00574       // send info about own neighborhood
00575       EuclideanNeighborMessage message;
00576       message.set_msg_id( EUCLIDEAN_NEIGHBOR_MESSAGE );
00577       // FIXME: isn't there a better way of doing this? problem here is
00578       //        without having const, and passing dmaps per value, not
00579       //        reference, where even copy constructor is called!
00580       DistanceMap dmap = this->neighborhood().neighbor_distance_map();
00581       message.set_neighbors( dmap );
00582       radio_->send( Radio::BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message );
00583       state_ = eu_work;
00584    }
00585    // ----------------------------------------------------------------------
00586    template<typename OsModel_P,
00587             typename Radio_P,
00588             typename Clock_P,
00589             typename Distance_P,
00590             typename Debug_P,
00591             typename SharedData_P,
00592             typename DistancePair_P>
00593    bool
00594    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00595    process_euclidean_neighbor_message( node_id_t from, size_t len, block_data_t* data )
00596    {
00597       EuclideanNeighborMessage* msg = (EuclideanNeighborMessage*)data;
00598 
00599       // set neighborhood of received node
00600       // FIXME: isn't there a better way of doing this? problem here is
00601       //        without having const, and passing dmaps per value, not
00602       //        reference, where even copy constructor is called!
00603       DistanceMap dmap = msg->neighbors();
00604       this->neighborhood().update_nneighbors( from, dmap );
00605 
00606       // if source is valid anchor, send anchor-message
00607       NeighborhoodIterator it = this->neighborhood().find( from );
00608       if ( it == this->neighborhood().end_neighborhood() )
00609          return true;
00610 
00611       if ( it->second->is_anchor() && it->second->is_valid() )
00612       {
00613          EuclideanAnchorMessage message;
00614          message.set_msg_id( EUCLIDEAN_ANCHOR_MESSAGE );
00615          message.set_anchor( it->second->node() );
00616          message.set_anchor_position( it->second->pos() );
00617          message.set_distance( it->second->distance() );
00618          radio_->send( Radio::BROADCAST_ADDRESS,
00619                       message.buffer_size(), (block_data_t*)&message );
00620       }
00621 
00622       return true;
00623    }
00624    // ----------------------------------------------------------------------
00625    template<typename OsModel_P,
00626             typename Radio_P,
00627             typename Clock_P,
00628             typename Distance_P,
00629             typename Debug_P,
00630             typename SharedData_P,
00631             typename DistancePair_P>
00632    bool
00633    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00634    process_euclidean_anchor_message( node_id_t from, size_t len, block_data_t* data )
00635    {
00636       if ( state_ == eu_finished )
00637             return true;
00638 
00639       EuclideanAnchorMessage* msg = (EuclideanAnchorMessage*)data;
00640 
00641       node_id_t anchor = msg->anchor();
00642       Vec anchor_pos = msg->anchor_position();
00643 
00644       // if anchor receives message about another anchor, the real distance
00645       // is calculated and sent as new anchor-message
00646       if ( this->shared_data().is_anchor() )
00647       {
00648          if ( this->neighborhood().find( anchor ) == this->neighborhood().end_neighborhood() )
00649             this->neighborhood().update_anchor( anchor, anchor_pos );
00650          else
00651             return true;
00652 
00653          double distance = euclidean_distance( anchor_pos, this->shared_data().position() );
00654          EuclideanAnchorMessage message;
00655          message.set_msg_id( EUCLIDEAN_ANCHOR_MESSAGE );
00656          message.set_anchor( anchor );
00657          message.set_anchor_position( anchor_pos );
00658          message.set_distance( distance );
00659          radio_->send(  Radio::BROADCAST_ADDRESS,
00660                       message.buffer_size(), (block_data_t*)&message );
00661 
00662          return true;
00663       }
00664 
00665       this->neighborhood().update_anchor( anchor, anchor_pos );
00666       this->neighborhood().update_nneighbor( anchor, from, msg->distance() );
00667 
00668       execute_euclidean( anchor );
00669 
00670       return true;
00671    }
00672    // ----------------------------------------------------------------------
00673    template<typename OsModel_P,
00674             typename Radio_P,
00675             typename Clock_P,
00676             typename Distance_P,
00677             typename Debug_P,
00678             typename SharedData_P,
00679             typename DistancePair_P>
00680    void
00681    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00682    execute_euclidean( node_id_t anchor )
00683    {
00684       NeighborhoodIterator it = this->neighborhood().find( anchor );
00685       //In case that we have not yet estimated a distance to this anchor
00686       if ( !it->second->is_valid() )
00687       {
00688          double distance = -1;
00689 
00690          switch ( algo_ )
00691          {
00692             case eu_algo_normal:
00693                distance = find_anchor_distance( it->second->node() );
00694                break;
00695 
00696             case eu_algo_opt:
00697                distance = find_anchor_distance_opt( it->second->node() );
00698                break;
00699          }
00700 
00701          if ( distance == -1 )
00702          {
00703 #ifdef LOCALIZATION_DISTANCEBASED_EUCLIDEAN_DEBUG
00704             debug_->debug(  "Distance to anchor %d is -1\n", anchor );
00705 #endif
00706             return;
00707          }
00708          else
00709          {
00710 #ifdef LOCALIZATION_DISTANCEBASED_EUCLIDEAN_DEBUG
00711             debug_->debug(  "Distance to anchor %d is %f\n", anchor, distance );
00712 #endif
00713          }
00714 
00715          it->second->set_distance( distance );
00716          EuclideanAnchorMessage message;
00717          message.set_msg_id( EUCLIDEAN_ANCHOR_MESSAGE );
00718          message.set_anchor( it->second->node() );
00719          message.set_anchor_position( it->second->pos() );
00720          message.set_distance( it->second->distance() );
00721          radio_->send(  Radio::BROADCAST_ADDRESS,
00722                       message.buffer_size(), (block_data_t*)&message );
00723 
00724          // if floodlimit reached, finished
00725          if ( this->neighborhood().valid_anchor_cnt() >= (int)this->shared_data().floodlimit() )
00726             state_ = eu_finished;
00727 
00728       }
00729    }
00730    // ----------------------------------------------------------------------
00731    template<typename OsModel_P,
00732             typename Radio_P,
00733             typename Clock_P,
00734             typename Distance_P,
00735             typename Debug_P,
00736             typename SharedData_P,
00737             typename DistancePair_P>
00738    double
00739    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00740    find_anchor_distance( node_id_t anchor )
00741    {
00742       double distance = -1;
00743       bool leave = false;
00744 
00745       for ( NeighborhoodIterator it1 = this->neighborhood().begin_neighborhood(); it1 != this->neighborhood().end_neighborhood(); ++it1 )
00746       {
00747          for ( NeighborhoodIterator it2 = it1; it2 != this->neighborhood().end_neighborhood(); ++it2 )
00748          {
00749             if ( it1 == it2 )
00750                continue;
00751 
00752             // check, that all needed distances exist
00753             if ( !this->neighborhood().has_valid_neighbor( it1->first ) ||
00754                   !this->neighborhood().has_valid_neighbor( it2->first ) ||
00755                   !this->neighborhood().has_valid_nneighbor( it1->first, it2->first ) ||
00756                   !this->neighborhood().has_valid_nneighbor( it1->first, anchor ) ||
00757                   !this->neighborhood().has_valid_nneighbor( it2->first, anchor ) )
00758                continue;
00759 
00760             double self_n1 = this->neighborhood().neighbor_distance( it1->first );
00761             double self_n2 = this->neighborhood().neighbor_distance( it2->first );
00762             double n1_n2 = this->neighborhood().nneighbor_distance( it1->first, it2->first );
00763             double n1_anchor = this->neighborhood().nneighbor_distance( it1->first, anchor );
00764             double n2_anchor = this->neighborhood().nneighbor_distance( it2->first, anchor );
00765 
00766             // check collinearity
00767             switch ( cc_std_ )
00768             {
00769                case eu_cc_std_strict:
00770                   if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) ||
00771                         is_collinear( n1_anchor, n2_anchor, n1_n2, col_measure_ ) )
00772                      continue;
00773                   break;
00774 
00775                case eu_cc_std_lax:
00776                   if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) &&
00777                         is_collinear( n1_anchor, n2_anchor, n1_n2, col_measure_ ) )
00778                      continue;
00779                   break;
00780 
00781                case eu_cc_std_none:
00782                   ;
00783             }
00784 
00785             DistancePair dp = trilateration_distance<OsModel, DistancePair>( self_n1, self_n2, n1_n2, n1_anchor, n2_anchor );
00786             if ( dp.first == -1 )
00787                continue;
00788 
00789             NodeList nl_nv = find_unique_neighbor_neighbors( anchor, it1->first, it2->first );
00790             NodeList nl_cn = find_common_neighbor_neighbors( anchor, it1->first, it2->first );
00791             double dist_nv = neighbor_vote( anchor, it1->first, it2->first, dp, nl_nv );
00792             double dist_cn = common_neighbor( anchor, it1->first, it2->first, dp, nl_cn );
00793 
00794             if ( dist_nv == -1 && dist_cn == -1 )
00795                continue;
00796 
00797             switch ( vote_)
00798             {
00799                case eu_vote_nv:
00800                {
00801                   if ( dist_nv != -1 ) distance = dist_nv;
00802                   else continue;
00803 
00804                   break;
00805                }
00806                case eu_vote_cn:
00807                {
00808                   if ( dist_cn != -1 ) distance = dist_cn;
00809                   else continue;
00810 
00811                   break;
00812                }
00813                case eu_vote_nvcn:
00814                {
00815                   if ( dist_cn != -1 ) distance = dist_cn;
00816                   if ( dist_nv != -1 ) distance = dist_nv;
00817                   else continue;
00818 
00819                   break;
00820                }
00821                case eu_vote_cnnv:
00822                {
00823                   if ( dist_nv != -1 ) distance = dist_nv;
00824                   if ( dist_cn != -1 ) distance = dist_cn;
00825                   else continue;
00826 
00827                   break;
00828                }
00829             }// switch vote_
00830 
00831             leave = true;
00832             break;
00833          }// for it2
00834 
00835          if ( leave ) break;
00836       }// for it1
00837 
00838       return distance;
00839    }
00840    // ----------------------------------------------------------------------
00841    template<typename OsModel_P,
00842             typename Radio_P,
00843             typename Clock_P,
00844             typename Distance_P,
00845             typename Debug_P,
00846             typename SharedData_P,
00847             typename DistancePair_P>
00848    double
00849    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00850    find_anchor_distance_opt( node_id_t anchor )
00851    {
00852       double distance = -1;
00853       double best_nv = -1;
00854       double best_cn = -1;
00855       double max_measure_nv = DBL_MIN;
00856       double max_measure_cn = DBL_MIN;
00857 
00858       for ( NeighborhoodIterator
00859                it1 = this->neighborhood().begin_neighborhood();
00860                it1 != this->neighborhood().end_neighborhood();
00861                ++it1 )
00862       {
00863          for ( NeighborhoodIterator
00864                   it2 = it1;
00865                   it2 != this->neighborhood().end_neighborhood();
00866                   ++it2 )
00867          {
00868             if ( it1 == it2 )
00869                continue;
00870 
00871             // check, that all needed distance estimations to neighboring nodes exist
00872             if ( !this->neighborhood().has_valid_neighbor( it1->first ) ||
00873                   !this->neighborhood().has_valid_neighbor( it2->first ) ||
00874                   !this->neighborhood().has_valid_nneighbor( it1->first, it2->first ) ||
00875                   !this->neighborhood().has_valid_nneighbor( it1->first, anchor ) ||
00876                   !this->neighborhood().has_valid_nneighbor( it2->first, anchor ) )
00877                continue;
00878 
00879             double self_n1 = this->neighborhood().neighbor_distance( it1->first );
00880             double self_n2 = this->neighborhood().neighbor_distance( it2->first );
00881             double n1_anchor = this->neighborhood().nneighbor_distance( it1->first, anchor );
00882             double n2_anchor = this->neighborhood().nneighbor_distance( it2->first, anchor );
00883             double n1_n2 = this->neighborhood().nneighbor_distance( it1->first, it2->first );
00884 
00885             // check collinearity
00886             switch ( cc_std_ )
00887             {
00888                case eu_cc_std_strict:
00889                   if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) ||
00890                         is_collinear( n1_anchor, n2_anchor, n1_n2, col_measure_ ) )
00891                      continue;
00892                   break;
00893 
00894                case eu_cc_std_lax:
00895                   if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) &&
00896                         is_collinear( n1_anchor, n2_anchor, n1_n2, col_measure_ ) )
00897                      continue;
00898                   break;
00899 
00900                case eu_cc_std_none:
00901                   ;
00902             }
00903 
00904             DistancePair dp = trilateration_distance<OsModel, DistancePair>( self_n1, self_n2, n1_n2, n1_anchor, n2_anchor );
00905 
00906             if ( dp.first > -1.00000000001 && dp.first < -0.999999999999 )
00907             {
00908                continue;
00909             }
00910 
00911             double measure;
00912             NodeList nl = find_common_neighbor_neighbors_opt( anchor, it1->first, it2->first, measure );
00913 
00914             double dist_nv = neighbor_vote( anchor, it1->first, it2->first, dp, nl );
00915             double dist_cn = common_neighbor( anchor, it1->first, it2->first, dp, nl );
00916 
00917             if ( dist_cn > -1.000000001 && dist_cn < -0.9999999999 && max_measure_cn < measure && measure > 0 )
00918             {
00919                max_measure_cn = measure;
00920                best_cn = dist_cn;
00921             }
00922 
00923             if ( dist_nv > -1.000000001 && dist_nv < -0.9999999999 && max_measure_nv < measure && measure > 0 )
00924             {
00925                max_measure_nv = measure;
00926                best_nv = dist_nv;
00927             }
00928          }// for it2
00929       }// for it1
00930 
00931       switch ( vote_)
00932       {
00933          case eu_vote_nv:
00934          {
00935             if ( best_nv > -1.000000001 && best_nv < -0.9999999999 ) distance = best_nv;
00936             break;
00937          }
00938          case eu_vote_cn:
00939          {
00940             if ( best_cn > -1.000000001 && best_cn < -0.9999999999 ) distance = best_cn;
00941             break;
00942          }
00943          case eu_vote_nvcn:
00944          {
00945             if ( best_cn > -1.000000001 && best_cn < -0.9999999999 ) distance = best_cn;
00946             if (best_nv > -1.000000001 && best_nv < -0.9999999999 ) distance = best_nv;
00947             break;
00948          }
00949          case eu_vote_cnnv:
00950          {
00951             if ( best_nv > -1.0000000001 && best_nv < -0.9999999999 -1 ) distance = best_nv;
00952             if ( best_cn > -1.0000000001 && best_cn < -0.9999999999 ) distance = best_cn;
00953             break;
00954          }
00955       }// switch vote_
00956 
00957       return distance;
00958    }
00959    // ----------------------------------------------------------------------
00960    template<typename OsModel_P,
00961             typename Radio_P,
00962             typename Clock_P,
00963             typename Distance_P,
00964             typename Debug_P,
00965             typename SharedData_P,
00966             typename DistancePair_P>
00967    typename LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::NodeList
00968    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
00969    find_unique_neighbor_neighbors( node_id_t anchor, node_id_t n1, node_id_t n2 )
00970    {
00971       NodeList temp;
00972 
00973       for ( NeighborhoodIterator
00974                it = this->neighborhood().begin_neighborhood();
00975                it != this->neighborhood().end_neighborhood();
00976                ++it )
00977       {
00978          // node is not n1 or n2, and connected to self and anchor
00979          if ( it->first == n1 || it->first == n2 || it->first == anchor ||
00980                !this->neighborhood().has_valid_neighbor( it->first ) ||
00981                !this->neighborhood().has_valid_nneighbor( it->first, anchor ) )
00982             continue;
00983 
00984          // node is connected to n1 and n2
00985          if ( !this->neighborhood().has_valid_nneighbor( n1, it->first ) &&
00986                !this->neighborhood().has_valid_nneighbor( n2, it->first ) )
00987             continue;
00988 
00989          temp.push_back( it->first );
00990       }
00991 
00992       return temp;
00993    }
00994    // ----------------------------------------------------------------------
00995    template<typename OsModel_P,
00996             typename Radio_P,
00997             typename Clock_P,
00998             typename Distance_P,
00999             typename Debug_P,
01000             typename SharedData_P,
01001             typename DistancePair_P>
01002    typename LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::NodeList
01003    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
01004    find_common_neighbor_neighbors( node_id_t anchor, node_id_t n1, node_id_t n2 )
01005    {
01006       NodeList temp;
01007 
01008       for ( NeighborhoodIterator
01009                it = this->neighborhood().begin_neighborhood();
01010                it != this->neighborhood().end_neighborhood();
01011                ++it )
01012       {
01013          // node is not n1 or n2, and connected to self and anchor
01014          if ( it->first == n1 || it->first == n2 || it->first == anchor ||
01015                !this->neighborhood().has_valid_neighbor( it->first ) ||
01016                !this->neighborhood().has_valid_nneighbor( it->first, anchor ) )
01017             continue;
01018 
01019          // node is connected to n1 and n2
01020          if ( !this->neighborhood().has_valid_nneighbor( n1, it->first ) ||
01021                !this->neighborhood().has_valid_nneighbor( n2, it->first ) )
01022             continue;
01023 
01024          temp.push_back( it->first );
01025       }
01026 
01027       return temp;
01028    }
01029    // ----------------------------------------------------------------------
01030    template<typename OsModel_P,
01031             typename Radio_P,
01032             typename Clock_P,
01033             typename Distance_P,
01034             typename Debug_P,
01035             typename SharedData_P,
01036             typename DistancePair_P>
01037    typename LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::NodeList
01038    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
01039    find_common_neighbor_neighbors_opt( node_id_t anchor, node_id_t n1,node_id_t n2, double& col_measure )
01040    {
01041       NodeList temp;
01042       col_measure = DBL_MIN;
01043 
01044       for ( NeighborhoodIterator
01045                it = this->neighborhood().begin_neighborhood();
01046                it != this->neighborhood().end_neighborhood();
01047                ++it )
01048       {
01049          // node is not n1 or n2, and connected to self and anchor
01050          if ( it->first == n1 || it->first == n2 || it->first == anchor ||
01051                !this->neighborhood().has_valid_neighbor( it->first ) ||
01052                !this->neighborhood().has_valid_nneighbor( it->first, anchor ) )
01053             continue;
01054 
01055          // node is connected to n1 and n2
01056          if ( !this->neighborhood().has_valid_nneighbor( n1, it->first ) ||
01057                !this->neighborhood().has_valid_nneighbor( n2, it->first ) )
01058             continue;
01059 
01060          double n1_n2 = this->neighborhood().nneighbor_distance( n1, n2 );
01061          double n1_n3 = this->neighborhood().nneighbor_distance( n1, it->first );
01062          double n2_n3 = this->neighborhood().nneighbor_distance( n2, it->first );
01063 
01064          double tmp_measure = collinear_measure( n1_n2, n1_n3, n2_n3 );
01065 
01066          if ( tmp_measure > col_measure )
01067          {
01068             col_measure = tmp_measure;
01069 
01070             temp.clear();
01071             temp.push_back( it->first );
01072          }
01073       }
01074 
01075       return temp;
01076    }
01077    // ----------------------------------------------------------------------
01078    template<typename OsModel_P,
01079             typename Radio_P,
01080             typename Clock_P,
01081             typename Distance_P,
01082             typename Debug_P,
01083             typename SharedData_P,
01084             typename DistancePair_P>
01085    double
01086    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
01087    neighbor_vote( node_id_t anchor, node_id_t n1, node_id_t n2, DistancePair& dp1, NodeList& nl )
01088    {
01089       if ( nl.empty() )
01090       {
01091          return -1;
01092       }
01093 
01094       // temporary workaround. update to 2D/3D should follow soon, so euclidean
01095       // will exclusively work with NodeLists.
01096       NodeList nl_refs;
01097       nl_refs.push_back( n1 );
01098       nl_refs.push_back( n2 );
01099 
01100       Statistics stat1, stat2;
01101       stat1 += dp1.first;
01102       stat2 += dp1.second;
01103 
01104       for ( NodeListIterator it = nl.begin(); it != nl.end(); ++it )
01105       {
01106          node_id_t n3 = *it;
01107 
01108          for ( NodeListIterator
01109                   it_refs = nl_refs.begin();
01110                   it_refs != nl_refs.end();
01111                   ++it_refs )
01112          {
01113 
01114             node_id_t n1_2 = *it_refs;
01115             if ( !this->neighborhood().has_nneighbor( n1_2, n3 ) )
01116                continue;
01117 
01118             double self_n12 = this->neighborhood().neighbor_distance( n1_2 );
01119             double self_n3 = this->neighborhood().neighbor_distance( n3 );
01120             double n12_n3 = this->neighborhood().nneighbor_distance( n1_2, n3 );
01121             double n12_anchor = this->neighborhood().nneighbor_distance( n1_2, anchor );
01122             double n3_anchor = this->neighborhood().nneighbor_distance( n3, anchor );
01123 
01124             // check collinearity
01125             switch ( cc_nv_ )
01126             {
01127                case eu_cc_nv_strict:
01128                   if ( is_collinear( self_n12, self_n3, n12_n3, col_measure_ ) ||
01129                         is_collinear( n12_n3, n12_anchor, n3_anchor, col_measure_ ) )
01130                      continue;
01131                   break;
01132 
01133                case eu_cc_nv_lax:
01134                   if ( is_collinear( self_n12, self_n3, n12_n3, col_measure_ ) &&
01135                         is_collinear( n12_n3, n12_anchor, n3_anchor, col_measure_ ) )
01136                      continue;
01137                   break;
01138 
01139                case eu_cc_nv_none:
01140                   ;
01141             }
01142 
01143             DistancePair dp2 = trilateration_distance<OsModel, DistancePair>( self_n12, self_n3, n12_n3, n12_anchor, n3_anchor );
01144             if ( dp2.first > -1.00000000001 && dp2.first < -0.999999999999)
01145                continue;
01146 
01147             enum ChooseDist { d11, d12, d21, d22 } ch_dist = d11;
01148             double dev_sel = fabs( stat1.mean() - dp2.first );
01149 
01150             if ( fabs( stat1.mean() - dp2.second ) < dev_sel )
01151             {
01152                dev_sel = fabs( stat1.mean() - dp2.second );
01153                ch_dist = d12;
01154             }
01155             if ( fabs( stat2.mean() - dp2.first ) < dev_sel )
01156             {
01157                dev_sel = fabs( stat2.mean() - dp2.first );
01158                ch_dist = d21;
01159             }
01160             if ( fabs( stat2.mean() - dp2.second ) < dev_sel )
01161             {
01162                dev_sel = fabs( stat2.mean() - dp2.second );
01163                ch_dist = d22;
01164             }
01165 
01166             switch ( ch_dist )
01167             {
01168                case d11:
01169                case d22:
01170                {
01171                   stat1 += dp2.first;
01172                   stat2 += dp2.second;
01173                   continue;
01174                }
01175                case d12:
01176                case d21:
01177                {
01178                   stat1 += dp2.second;
01179                   stat2 += dp2.first;
01180                   continue;
01181                }
01182             }// switch
01183          }// for NodeList refs
01184       }// for NodeList nl
01185 
01186 #ifdef LOCALIZATION_DISTANCEBASED_EUCLIDEAN_DEBUG
01187 //       double real = euclidean_distance( anchor.real_position(), node().real_position() );
01188 //       DEBUG( owner().logger(),
01189 //          "Stats: "
01190 //             << std::endl
01191 //             << stat1 << ";;; " << stat2
01192 //             << std::endl
01193 //             << "Real: " << real << ": "
01194 //             << std::endl
01195 //             << stat1.mean() << "; " << stat1.std_dev() << " <= " << stat1.mean()*0.05
01196 //             << " | "
01197 //             << stat2.mean() << "; " << stat2.std_dev() << " <= " << stat2.mean()*0.05
01198 //             << std::endl );
01199 #endif
01200 
01201       if ( stat1.std_dev() > stat1.mean()*0.05 && stat2.std_dev() > stat2.mean()*0.05 )
01202          return -1;
01203 
01204       if ( stat1.std_dev()*3 < stat2.std_dev() )
01205          return stat1.mean();
01206       else if ( stat2.std_dev()*3 < stat1.std_dev() )
01207          return stat2.mean();
01208 
01209       return -1;
01210    }
01211    // ----------------------------------------------------------------------
01212    template<typename OsModel_P,
01213             typename Radio_P,
01214             typename Clock_P,
01215             typename Distance_P,
01216             typename Debug_P,
01217             typename SharedData_P,
01218             typename DistancePair_P>
01219    double
01220    LocalizationEuclideanModule<OsModel_P, Radio_P, Clock_P, Distance_P, Debug_P, SharedData_P, DistancePair_P>::
01221    common_neighbor( node_id_t anchor, node_id_t n1, node_id_t n2, DistancePair& dp, NodeList& nl )
01222    {
01223       if ( nl.empty() ) return -1;
01224 
01225       for ( NodeListIterator
01226                it = nl.begin();
01227                it != nl.end();
01228                ++it )
01229       {
01230          node_id_t n3 = *it;
01231 
01232          double self_n1 = this->neighborhood().neighbor_distance( n1 );
01233          double self_n2 = this->neighborhood().neighbor_distance( n2 );
01234          double self_n3 = this->neighborhood().neighbor_distance( n3 );
01235          double n1_n2, n1_anchor, n2_anchor, n3_n1, n3_n2;
01236          if ( this->neighborhood().has_valid_nneighbor( n1, n2 ) &&
01237                this->neighborhood().has_valid_nneighbor( anchor, n1 ) &&
01238                this->neighborhood().has_valid_nneighbor( anchor, n2 ) &&
01239                this->neighborhood().has_valid_nneighbor( n3, n1 ) &&
01240                this->neighborhood().has_valid_nneighbor( n3, n2 ) )
01241          {
01242             n1_n2 = this->neighborhood().nneighbor_distance( n1, n2 );
01243             n1_anchor = this->neighborhood().nneighbor_distance( anchor, n1 );
01244             n2_anchor = this->neighborhood().nneighbor_distance( anchor, n2 );
01245             n3_n1 = this->neighborhood().nneighbor_distance( n3, n1 );
01246             n3_n2 = this->neighborhood().nneighbor_distance( n3, n2 );
01247          }
01248          else
01249             continue;
01250 
01251          // check collinearity
01252          switch ( cc_cn_ )
01253          {
01254             case eu_cc_cn_strict:
01255                if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) ||
01256                      is_collinear( n1_n2, n3_n1, n3_n2, col_measure_ ) ||
01257                      is_collinear( n1_n2, n1_anchor, n2_anchor, col_measure_ ) )
01258                   continue;
01259                break;
01260 
01261             case eu_cc_cn_lax:
01262                if ( is_collinear( self_n1, self_n2, n1_n2, col_measure_ ) &&
01263                      is_collinear( n1_n2, n3_n1, n3_n2, col_measure_ ) &&
01264                      is_collinear( n1_n2, n1_anchor, n2_anchor, col_measure_ ) )
01265                   continue;
01266                break;
01267 
01268             case eu_cc_cn_none:
01269                ;
01270          }
01271 
01272          // distancepair self-n3
01273          DistancePair dp_sn3 = trilateration_distance<OsModel, DistancePair>(
01274                                  self_n1, self_n2, n1_n2, n3_n1, n3_n2 );
01275          if ( dp_sn3.first == -1 )
01276             continue;
01277 
01278          int side_n3 = 0;
01279          if ( fabs( self_n3 - dp_sn3.first ) < fabs( self_n3 - dp_sn3.second ) )
01280             side_n3 = 1;
01281          else
01282             side_n3 = -1;
01283 
01284          // distancepair n3-anchor
01285          DistancePair dp_n3a = trilateration_distance<OsModel, DistancePair>(
01286                                  n3_n1, n3_n2, n1_n2, n1_anchor, n2_anchor );
01287          if ( dp_n3a.first == -1 )
01288             continue;
01289 
01290          int side_a = 0;
01291          double n3_a = this->neighborhood().find( n3 )->second->neighbor_distance( anchor );
01292          if ( fabs( n3_a - dp_n3a.first ) < fabs( n3_a - dp_n3a.second ) )
01293             side_a = 1;
01294          else
01295             side_a = -1;
01296 
01297 #ifdef LOCALIZATION_DISTANCEBASED_EUCLIDEAN_DEBUG
01298 //          double real_dist = euclidean_distance( node().real_position(), anchor.real_position() );
01299 //          DEBUG( owner().logger(),
01300 //             real_dist << ": " << dp.first << "; " << dp.second
01301 //                << " :: " << side_n3 * side_a
01302 //                << std::endl
01303 //                << self_n3 << ": " << dp_sn3.first << "; " << dp_sn3.second
01304 //                << std::endl
01305 //                << n3_a    << ": " << dp_n3a.first << "; " << dp_n3a.second
01306 //                << std::endl );
01307 #endif
01308 
01309          if ( side_n3 == 1 && side_a == 1 )
01310             return dp.first;
01311          else if ( side_n3 * side_a == -1 || ( side_n3 == -1 && side_a == -1 ) )
01312             return dp.second;
01313       }// for
01314 
01315       return -1;
01316    }
01317 
01318 }// namespace wiselib
01319 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines