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 ** Author: Víctor López Ferrando, victorlopez90@gmail.com ** 00020 ***************************************************************************/ 00021 #ifndef __ALGORITHMS_TOPOLOGY_FLSS_TOPOLOGY_H__ 00022 #define __ALGORITHMS_TOPOLOGY_FLSS_TOPOLOGY_H__ 00023 00024 #include "algorithms/topology/lmst/lmst_topology_message.h" 00025 #include "algorithms/topology/topology_control_base.h" 00026 #include "util/pstl/priority_queue.h" 00027 #include "util/pstl/vector_static.h" 00028 #include "util/pstl/pair.h" 00029 #include <queue> // TODO: use pSTL queue 00030 #include <limits> 00031 00032 00033 #define DEBUG_FLSS_TOPOLOGY 00034 00035 namespace wiselib 00036 { 00037 00043 template<typename OsModel_P, 00044 uint16_t K, 00045 typename Localization_P, 00046 uint16_t MAX_NODES, 00047 typename Radio_P = typename OsModel_P::Radio, 00048 typename Timer_P = typename OsModel_P::Timer> 00049 class FlssTopology : 00050 public TopologyBase<OsModel_P> 00051 { 00052 public: 00053 typedef OsModel_P OsModel; 00054 typedef Localization_P Localization; 00055 typedef Radio_P Radio; 00056 typedef Timer_P Timer; 00057 typedef typename Localization::float_t float_t; 00058 00059 #ifdef DEBUG_FLSS_TOPOLOGY 00060 typedef typename OsModel::Debug Debug; 00061 #endif 00062 00063 typedef FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P> self_type; 00064 typedef LmstTopologyMessage<OsModel, Radio, float_t> TopologyMessage; 00065 00066 typedef typename Localization::position_t Position; 00067 00068 typedef typename Radio::node_id_t node_id_t; 00069 typedef typename Radio::size_t size_t; 00070 typedef typename Radio::block_data_t block_data_t; 00071 00072 typedef typename Timer::millis_t millis_t; 00073 00074 typedef pair<float_t, node_id_t> PPI; 00075 typedef vector_static<OsModel, node_id_t, MAX_NODES> Neighbors; 00076 static const uint8_t POSITION_SIZE = sizeof( Position ); 00077 00080 FlssTopology(); 00081 ~FlssTopology(); 00083 00086 void enable( void ); 00087 void disable( void ); 00089 00092 void timer_elapsed( void *userdata ); 00094 00097 void receive( node_id_t from, size_t len, block_data_t *data ); 00099 00100 inline void set_startup_time( millis_t startup_time ) 00101 { startup_time_ = startup_time; }; 00102 00103 inline void set_work_period( millis_t work_period ) 00104 { work_period_ = work_period; }; 00105 00106 Neighbors &topology() { 00107 return N; 00108 } 00109 00110 float_t range_assignment() { 00111 return radius_; 00112 } 00113 00114 void init( Radio& radio, Timer& timer, Debug& debug ) { 00115 radio_ = &radio; 00116 timer_ = &timer; 00117 debug_ = &debug; 00118 } 00119 00120 void destruct() { 00121 } 00122 00123 private: 00124 00125 Radio& radio() 00126 { return *radio_; } 00127 00128 Timer& timer() 00129 { return *timer_; } 00130 00131 Debug& debug() 00132 { return *debug_; } 00133 00134 Radio * radio_; 00135 Timer * timer_; 00136 Debug * debug_; 00137 00140 enum FlssTopologyMsgIds { 00141 LtMsgIdBroadcastPosition = 200, 00142 LtMsgIdNeighbourNotification = 201, 00143 }; 00144 00147 Neighbors N; // Topology 00148 float_t radius_; 00150 00151 millis_t startup_time_; 00152 millis_t work_period_; 00153 00154 TopologyMessage positionMessage; 00155 uint8_t neighbourMessage; 00156 00157 void generate_topology(); 00158 int16_t max_flow(node_id_t source, node_id_t sink); 00159 int16_t find_path_bfs(node_id_t source, node_id_t sink); 00160 00161 int n; 00162 const static int32_t inf = 2000000000; 00163 00164 Localization localization_; 00165 00166 typedef pair<int, int> PII; 00167 vector_static<OsModel, bool, MAX_NODES> seen; 00168 vector_static<OsModel, node_id_t, MAX_NODES> from; 00169 vector_static<OsModel, node_id_t, MAX_NODES> NV; 00170 vector_static<OsModel, Position, MAX_NODES> Pos; 00171 vector_static<OsModel, vector_static<OsModel, uint8_t, MAX_NODES>, MAX_NODES> capacity; 00172 vector_static<OsModel, vector_static<OsModel, node_id_t, MAX_NODES>, MAX_NODES> G; 00173 vector_static<OsModel, vector_static<OsModel, uint8_t, MAX_NODES>, MAX_NODES> capacity_bak; 00174 vector_static<OsModel, vector_static<OsModel, node_id_t, MAX_NODES>, MAX_NODES> G_bak; 00175 priority_queue< OsModel, pair<float_t, PII >, MAX_NODES*10 > E; 00176 std::queue<node_id_t> Q; 00177 00178 }; 00179 // ----------------------------------------------------------------------- 00180 // ----------------------------------------------------------------------- 00181 // ----------------------------------------------------------------------- 00182 template<typename OsModel_P, 00183 uint16_t K, 00184 typename Localization_P, 00185 uint16_t MAX_NODES, 00186 typename Radio_P, 00187 typename Timer_P> 00188 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00189 FlssTopology() 00190 : os_ ( 0 ), 00191 startup_time_ ( 2000 ), 00192 work_period_ ( 5000 ), 00193 positionMessage( LtMsgIdBroadcastPosition ), 00194 neighbourMessage( LtMsgIdNeighbourNotification ) 00195 {}; 00196 // ----------------------------------------------------------------------- 00197 template<typename OsModel_P, 00198 uint16_t K, 00199 typename Localization_P, 00200 uint16_t MAX_NODES, 00201 typename Radio_P, 00202 typename Timer_P> 00203 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00204 ~FlssTopology() 00205 { 00206 #ifdef DEBUG_FLSS_TOPOLOGY 00207 debug().debug( "%i: FlssTopology Destroyed\n", radio().id() ); 00208 #endif 00209 }; 00210 // ----------------------------------------------------------------------- 00211 template<typename OsModel_P, 00212 uint16_t K, 00213 typename Localization_P, 00214 uint16_t MAX_NODES, 00215 typename Radio_P, 00216 typename Timer_P> 00217 void 00218 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00219 enable( void ) 00220 { 00221 radio().enable_radio(); 00222 #ifdef DEBUG_FLSS_TOPOLOGY 00223 debug().debug( "%i: FlssTopology Boots\n", radio().id() ); 00224 #endif 00225 radio().template reg_recv_callback<self_type, &self_type::receive>( 00226 this ); 00227 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00228 startup_time_, this, 0 ); 00229 #ifdef DEBUG_FLSS_TOPOLOGY 00230 debug().debug( "%i: FlssTopology Enables Localization\n", 00231 radio().id() ); 00232 #endif 00233 localization_.enable(); 00234 } 00235 // ----------------------------------------------------------------------- 00236 template<typename OsModel_P, 00237 uint16_t K, 00238 typename Localization_P, 00239 uint16_t MAX_NODES, 00240 typename Radio_P, 00241 typename Timer_P> 00242 void 00243 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00244 disable( void ) 00245 { 00246 #ifdef DEBUG_FLSS_TOPOLOGY 00247 debug().debug( "%i: Called FlssTopology::disable\n", radio().id() ); 00248 #endif 00249 localization_.disable(); 00250 } 00251 // ----------------------------------------------------------------------- 00252 template<typename OsModel_P, 00253 uint16_t K, 00254 typename Localization_P, 00255 uint16_t MAX_NODES, 00256 typename Radio_P, 00257 typename Timer_P> 00258 void 00259 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00260 timer_elapsed( void* userdata ) 00261 { 00262 #ifdef DEBUG_FLSS_TOPOLOGY 00263 debug().debug( "%i: Executing TimerElapsed 'FlssTopology'\n", 00264 radio().id() ); 00265 #endif 00266 00267 #ifdef DEBUG_FLSS_TOPOLOGY 00268 debug().debug( "%i: Generating topology\n", 00269 radio().id() ); 00270 #endif 00271 generate_topology(); 00272 TopologyBase<OsModel>::notify_listeners(); 00273 for ( size_t i = 0; i < N.size(); ++i ) 00274 radio().send( N[i], 1, (uint8_t*)&neighbourMessage ); 00275 Position pos = localization_.position(); 00276 #ifdef DEBUG_FLSS_TOPOLOGY 00277 debug().debug( "%i: Broadcasting position (%f, %f, %f)\n", 00278 radio().id(), pos.x, pos.y, pos.z ); 00279 #endif 00280 positionMessage.set_position( pos ); 00281 radio().send( radio().BROADCAST_ADDRESS, 1 + POSITION_SIZE, (uint8_t*)&positionMessage ); 00282 00283 timer().template set_timer<self_type, &self_type::timer_elapsed>( 00284 work_period_, this, 0 ); 00285 } 00286 // ----------------------------------------------------------------------- 00287 template<typename OsModel_P, 00288 uint16_t K, 00289 typename Localization_P, 00290 uint16_t MAX_NODES, 00291 typename Radio_P, 00292 typename Timer_P> 00293 void 00294 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00295 receive( node_id_t from, size_t len, block_data_t *data ) 00296 { 00297 if ( from == radio().id() ) 00298 return; 00299 00300 uint8_t msg_id = *data; 00301 if ( msg_id == LtMsgIdBroadcastPosition ) 00302 { 00303 TopologyMessage *msg = (TopologyMessage *)data; 00304 Position pos = msg->position(); 00305 #ifdef DEBUG_FLSS_TOPOLOGY 00306 debug().debug( "%i: Received position msg from %i: (%f, %f, %f)\n", 00307 radio().id(), from, pos.x, pos.y, pos.z ); 00308 #endif 00309 NV.push_back( from ); 00310 Pos.push_back( pos ); 00311 } 00312 else if ( msg_id == LtMsgIdNeighbourNotification ) 00313 { 00314 #ifdef DEBUG_FLSS_TOPOLOGY 00315 debug().debug( "%i: Received neighbourhood message from %i\n", 00316 radio().id(), from ); 00317 #endif 00318 size_t i = 0; 00319 while ( i < N.size() && N[i] != from ) 00320 ++i; 00321 if ( i == N.size() ) 00322 { 00323 #ifdef DEBUG_FLSS_TOPOLOGY 00324 debug().debug( "%i: Added node %i in N because I didn't have it\n", 00325 radio().id(), from ); 00326 #endif 00327 N.push_back( from ); 00328 } 00329 } 00330 } 00331 // ----------------------------------------------------------------------- 00332 template<typename OsModel_P, 00333 uint16_t K, 00334 typename Localization_P, 00335 uint16_t MAX_NODES, 00336 typename Radio_P, 00337 typename Timer_P> 00338 void 00339 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00340 generate_topology() 00341 { 00342 // Generalized Kruskal algorithm to get the minimum spanning K-connected graph 00343 // Ford-fulkerson algorithm used to check K-connection 00344 E.clear(); 00345 // Afegim l'arrel als veinss 00346 NV.push_back( radio().id() ); 00347 n = NV.size(); 00348 // Generem el graf i omplim la PQ amb arestes 00349 for (int i = 0; i < n; ++i) 00350 for (int j = i+1; j < n; ++j) { 00351 capacity[2*i][2*i+1] = 1; 00352 capacity[2*i+1][2*j] = 0; 00353 capacity[2*j+1][2*i] = 0; 00354 E.push(pair<float_t, PII >(dist(Pos[i], Pos[j]), PII(2*i+1, 2*j))); 00355 } 00356 for (int i=0; i<n; ++i) 00357 for (int j=0; j<n; ++j) 00358 if (capacity[i][j] > 0) 00359 G[i].push_back(j); 00360 G_bak = G; 00361 capacity_bak = capacity; 00362 for (int i = 0; i < E.size(); ++i) { 00363 if (max_flow(E.top().second.first, E.top().second.second) < K) { 00364 G[E.top().second.first][E.top().second.second] = true; 00365 G[E.top().second.second+1][E.top().second.first-1] = true; 00366 } 00367 bool finish = true; 00368 for (int i = 0; i < n-1; ++i) 00369 if (max_flow(2*i+1, 2*n-1) < K) 00370 finish = false; 00371 if (finish) 00372 break; 00373 } 00374 N.clear(); 00375 for (int i = 0; i < n-1; ++i) 00376 if (G[2*i+1][2*n-2]) 00377 N.push_back(i); 00378 NV.clear(); 00379 Pos.clear(); 00380 } 00381 // ----------------------------------------------------------------------- 00382 template<typename OsModel_P, 00383 uint16_t K, 00384 typename Localization_P, 00385 uint16_t MAX_NODES, 00386 typename Radio_P, 00387 typename Timer_P> 00388 int16_t 00389 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00390 max_flow(node_id_t source, node_id_t sink) 00391 { 00392 G = G_bak; 00393 capacity = capacity_bak; 00394 int16_t sol = 0; 00395 while (true) { 00396 int16_t path_capacity = find_path_bfs(source, sink); 00397 if (path_capacity == 0) 00398 break; 00399 else 00400 sol += path_capacity; 00401 } 00402 return sol; 00403 } 00404 // ----------------------------------------------------------------------- 00405 template<typename OsModel_P, 00406 uint16_t K, 00407 typename Localization_P, 00408 uint16_t MAX_NODES, 00409 typename Radio_P, 00410 typename Timer_P> 00411 int16_t 00412 FlssTopology<OsModel_P, K, Localization_P, MAX_NODES, Radio_P, Timer_P>:: 00413 find_path_bfs(node_id_t source, node_id_t sink) 00414 { 00415 for (int i = 0; i < n; ++i) 00416 seen[i] = false; 00417 for (int i = 0; i < n; ++i) 00418 from[i] = -1; 00419 Q = std::queue<node_id_t>(); 00420 Q.push(source); 00421 seen[source] = true; 00422 while (not Q.empty()) { 00423 node_id_t where = Q.front(); 00424 Q.pop(); 00425 bool finish = false; 00426 for (int i = 0; i < G[where].size(); ++i) 00427 if ( not seen[G[where][i]] and capacity[where][G[where][i]] > 0 ) { 00428 Q.push(G[where][i]); 00429 seen[G[where][i]] = true; 00430 from[G[where][i]] = where; 00431 if (G[where][i] == sink) { 00432 finish = true; 00433 break; 00434 } 00435 } 00436 if (finish) 00437 break; 00438 } 00439 node_id_t where = sink, path_cap = inf; 00440 while (from[where] > -1) { 00441 node_id_t prev = from[where]; 00442 path_cap = (path_cap < capacity[prev][where] ? path_cap : capacity[prev][where]); 00443 where = prev; 00444 } 00445 where = sink; 00446 while (from[where] > -1) { 00447 node_id_t prev = from[where]; 00448 capacity[prev][where] -= path_cap; 00449 where = prev; 00450 } 00451 if (path_cap == inf) 00452 return 0; 00453 else 00454 return path_cap; 00455 } 00456 } 00457 #endif