Wiselib
|
00001 #ifndef __TRIANGULATION_H__ 00002 #define __TRIANGULATION_H__ 00003 00004 #define DEBUG_TRIANGULATION 00005 00006 //#include "algorithms/routing/routing_base.h" 00007 #include "algorithms/localization/triangulation/triangulation_message.h" 00008 #include "algorithms/localization/localization_base.h" 00009 #include "util/delegates/delegate.hpp" 00010 //---------------------------------------------------- 00011 #include <math.h> 00012 //#include <cmath> 00013 #include <stdlib.h> 00014 #include <time.h> 00015 #include "internal_interface/routing_table/routing_table_static_array.h" 00016 //---------------------------------------------------- 00017 int __errno; 00018 //---------------------------------------------------- 00019 00020 namespace wiselib 00021 { 00022 00027 template<typename OsModel_P, 00028 typename Radio_P, 00029 typename Distance_P, 00030 typename Debug_P = typename OsModel_P::Debug> 00031 class Triangulation 00032 // : public LocalizationBase<OsModel_P,Radio_P> 00033 { 00034 public: 00035 typedef OsModel_P OsModel; 00036 typedef Radio_P Radio; 00037 typedef Debug_P Debug; 00038 typedef Distance_P Distance; 00039 00040 typedef StaticArrayRoutingTable <OsModel, Radio, 15, int> int_map_t; 00041 typedef typename int_map_t::iterator int_map_iterator_t; 00042 00043 00044 typedef Triangulation<OsModel, Radio, Distance, Debug> self_type; 00045 00046 typedef typename OsModel::Timer Timer; 00047 typedef typename Timer::millis_t millis_t; 00048 00049 typedef typename Radio::node_id_t node_id_t; 00050 typedef typename Radio::size_t size_t; 00051 typedef typename Radio::block_data_t block_data_t; 00052 typedef typename Radio::message_id_t message_id_t; 00053 00054 typedef TriangulationMessage<OsModel, Radio> Message; 00055 // -------------------------------------------------------------------- 00056 enum ErrorCodes 00057 { 00058 SUCCESS = OsModel::SUCCESS, 00059 ERR_UNSPEC = OsModel::ERR_UNSPEC, 00060 ERR_NOTIMPL = OsModel::ERR_NOTIMPL 00061 }; 00062 // -------------------------------------------------------------------- 00065 Triangulation(); 00066 ~Triangulation(); 00068 00071 void enable( void ); 00072 void disable( void ); 00074 00077 void send( ); 00079 00082 void receive( node_id_t from, size_t len, block_data_t *data ); 00084 00090 int getIndex(node_id_t); 00091 00097 int getNode (int); 00098 00102 void findP(); 00103 00108 void findCoordinatesP(); 00109 00115 void findPQ(); 00116 00122 void findCoordinatesPQ(); 00123 00127 void findCircle(); 00128 00135 int testCircle(int, int); 00136 00143 void setRating(node_id_t, node_id_t, int); //Absender-ID, 3. Dreiecks-ID, Bewertung 00144 00153 void setTriangleGlobal(node_id_t, node_id_t, node_id_t, int); 00154 00159 bool nodeInTriangles(); 00160 00167 int lookUpTrust(int, int); 00168 00174 int bestCircleIndex(node_id_t); 00175 00179 int max(int,int); 00180 00184 int min(int,int); 00185 00189 void coordinates_timer_elapsed( void *userdata ); 00190 00194 void complete_triangulation_timer_elapsed( void *userdata); 00195 00199 void select_best_circle_timer_elapsed( void *userdata); 00200 00204 void fourth_timer_elapsed( void *userdata); 00205 00209 void send_timer_elapsed( void *userdata); 00210 00214 void message_timer_elapsed (void *userdata); 00215 00216 // void reset_data(); 00217 00218 void triangles_changed(int); 00219 00220 typedef delegate1<void, int> localization_delegate_t; 00221 00222 // -------------------------------------------------------------------- 00223 template<class T, void (T::*TMethod)(int)> 00224 inline void reg_changed_callback( T *obj_pnt ) 00225 { 00226 callback_ = localization_delegate_t::from_method<T, TMethod>( obj_pnt ); 00227 }; 00228 // -------------------------------------------------------------------- 00229 inline void unreg_changed_callback( void ) 00230 { 00231 callback_ = localization_delegate_t(); 00232 } 00233 // -------------------------------------------------------------------- 00234 inline void notify_receivers( int value ) 00235 { 00236 if (callback_) 00237 callback_( value ); 00238 } 00239 00240 localization_delegate_t callback_; 00241 00242 int init( Radio& radio, Timer& timer, Debug& debug ) 00243 { 00244 radio_ = &radio; 00245 timer_ = &timer; 00246 debug_ = &debug; 00247 return SUCCESS; 00248 } 00249 00250 int init() 00251 { return ERR_NOTIMPL; } 00252 00253 int destruct() 00254 { return ERR_NOTIMPL; } 00255 00256 private: 00257 Radio& radio() 00258 { return *radio_; } 00259 00260 Timer& timer() 00261 { return *timer_; } 00262 00263 Debug& debug() 00264 { return *debug_; } 00265 00266 typename Radio::self_pointer_t radio_; 00267 typename Timer::self_pointer_t timer_; 00268 typename Debug::self_pointer_t debug_; 00269 00270 Distance dist_est_; 00271 00272 00273 enum MessageIds 00274 { 00275 DISTANCE_CHECK = 1, 00276 DISTANCE_RETURN = 2, 00277 DISTANCE_PROP = 3, 00278 CHECK_CIRCLE = 4, 00279 CHECK_CIRCLE_RETURN = 5, 00280 TRIANGLE_PROP = 6, 00281 ASKFORCIRCLE = 7, 00282 RETURN_CIRCLE = 8, 00283 RESET = 98, 00284 RESET_PROP = 99, 00285 00286 }; 00287 00288 enum Various 00289 { 00290 MESSAGES_SIZE = 15, 00291 NODECOUNT = 10, 00292 VECTORSIZE = 20, //1.5*nodecount reicht sicher 00293 MILLIS = 1000, 00294 POSITION_CHANGED = 0, 00295 UNKNOWN_POSITION = 1 00296 }; 00297 00298 short callback_id_; 00299 00300 struct circle { 00301 node_id_t idFirst, idSecond; 00302 int ratingFirst, ratingSecond; 00303 }; 00304 struct triangle { 00305 node_id_t idFirst, idSecond, idThird; 00306 bool prop; 00307 int trust; //1 für: alle stimmen zu, 2 für: einer siehts nicht, 3 für: zwei sehns nicht, 4 für: einer stimmt zu, einer lehnt ab, 5 für: zwei lehnen ab 00308 }; 00309 00310 typedef vector_static<OsModel,triangle,VECTORSIZE> position_t; 00311 00312 inline position_t *position() { 00313 if(nodeInTriangles) 00314 return &triangles; 00315 else 00316 return NULL; 00317 } 00318 00319 int_map_t neighbourMap; 00320 00321 float distances[NODECOUNT]; 00322 float ndistances[NODECOUNT][NODECOUNT]; 00323 float coordinates[NODECOUNT][2]; //für alle Knoten an [i][0] x und an [i][1] y 00324 00325 bool send_called; 00326 short neighbourCount; 00327 00328 int p_index; 00329 int q_index; 00330 node_id_t demandedCircleIDs[3]; 00331 00332 millis_t waitingTime1; 00333 millis_t waitingTime2; 00334 millis_t startupTime; 00335 00336 bool coordinates_timer_started; 00337 bool send_timer_iteration; 00338 bool coordinates_called; 00339 int send_timer_running; 00340 int complete_triangulation_timer_running; 00341 00342 vector_static<OsModel, circle, VECTORSIZE> foundCircles; 00343 vector_static<OsModel, triangle, VECTORSIZE> triangles; 00344 vector_static<OsModel, Message, MESSAGES_SIZE> messages; 00345 00346 00347 }; 00348 // ----------------------------------------------------------------------- 00349 // ----------------------------------------------------------------------- 00350 // ----------------------------------------------------------------------- 00351 template<typename OsModel_P, 00352 typename Radio_P, typename Distance_P, 00353 typename Debug_P> 00354 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00355 Triangulation() 00356 : os_ ( 0 ), 00357 callback_id_ ( 0 ), 00358 send_called(false), 00359 coordinates_timer_started(false), 00360 send_timer_iteration(true), 00361 neighbourCount(0), 00362 send_timer_running(0), 00363 complete_triangulation_timer_running(0), 00364 p_index(-1), q_index(-1), 00365 waitingTime1(8000), 00366 waitingTime2(3000), 00367 startupTime (5000) 00368 {}; 00369 // ----------------------------------------------------------------------- 00370 template<typename OsModel_P, 00371 typename Radio_P, typename Distance_P, 00372 typename Debug_P> 00373 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00374 ~Triangulation() 00375 { 00376 // debug().debug( "Triangulation:dtor\n" ); 00377 00378 }; 00379 // ----------------------------------------------------------------------- 00380 template<typename OsModel_P, 00381 typename Radio_P, typename Distance_P, 00382 typename Debug_P> 00383 void 00384 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00385 enable( void ) 00386 { 00387 #ifdef DEBUG_TRIANGULATION 00388 debug().debug( "Triangulation: Boot for %i - send_timer started \n", radio().id( ) ); 00389 #endif 00390 00391 radio().enable_radio( ); 00392 callback_id_ = radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00393 00394 reg_changed_callback<self_type, &self_type::triangles_changed>(this); 00395 00396 dist_est_.set_os(); 00397 dist_est_.enable(); 00398 00399 neighbourMap[radio().id()] = 0; 00400 00401 for(int i=0; i<NODECOUNT;i++) { 00402 distances[i] = 0; 00403 coordinates[i][0] = 0; 00404 coordinates[i][1] = 0; 00405 for(int j=0;j<NODECOUNT;j++) { 00406 ndistances[i][j]= 0; 00407 } 00408 } 00409 demandedCircleIDs[2] = -1; 00410 00411 timer().template set_timer<self_type, &self_type::send_timer_elapsed>( startupTime,this , 0 ); 00412 00413 } 00414 00415 template<typename OsModel_P, 00416 typename Radio_P, typename Distance_P, 00417 typename Debug_P> 00418 void 00419 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00420 disable( void ) 00421 { 00422 //debug().debug( "Triangulation: Disable\n" ); 00423 00424 radio().unreg_recv_callback( callback_id_ ); 00425 radio().disable( ); 00426 } 00427 00428 // ----------------------------------------------------------------------- 00429 00430 template<typename OsModel_P, 00431 typename Radio_P, typename Distance_P, 00432 typename Debug_P> 00433 void 00434 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00435 triangles_changed(int ID) { 00436 00437 if(ID == POSITION_CHANGED) { 00438 debug().debug("related triangles changed for %i \n", radio().id()); 00439 } 00440 00441 } 00442 00443 template<typename OsModel_P, 00444 typename Radio_P, typename Distance_P, 00445 typename Debug_P> 00446 int 00447 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00448 getIndex(node_id_t nodeID) { 00449 00450 for(int_map_iterator_t it = neighbourMap.begin(); it != neighbourMap.end(); it++) { 00451 if(it->first == nodeID) { 00452 return it->second; 00453 } 00454 } 00455 00456 if(neighbourMap.find(nodeID) == neighbourMap.end()) { //nodeID noch nicht gespeichert 00457 neighbourMap[nodeID] = 0; 00458 neighbourMap[nodeID] = neighbourMap.find(nodeID) - neighbourMap.begin(); 00459 } 00460 00461 return neighbourMap.find(nodeID) - neighbourMap.begin(); 00462 } 00463 00464 template<typename OsModel_P, 00465 typename Radio_P, typename Distance_P, 00466 typename Debug_P> 00467 int 00468 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00469 getNode(int abc) { 00470 00471 for(int_map_iterator_t it = neighbourMap.begin(); it != neighbourMap.end(); it++) { 00472 if(it->second == abc) { 00473 return it->first; 00474 } 00475 } 00476 return -1; 00477 } 00478 00479 template<typename OsModel_P, 00480 typename Radio_P, typename Distance_P, 00481 typename Debug_P> 00482 void 00483 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00484 coordinates_timer_elapsed (void* userdata) { 00485 00486 send_timer_iteration = false; 00487 coordinates_called = true; 00488 00489 if(p_index==-1 && q_index==-1) { 00490 findP(); 00491 00492 //Distanzen und p/q vorhanden, Kreise schon gesucht? 00493 if(foundCircles.size() == 0) { 00494 00495 findCircle(); 00496 00497 timer().template set_timer<self_type, &self_type::complete_triangulation_timer_elapsed>( waitingTime1, this, 0 ); 00498 } 00499 } 00500 } 00501 00502 00503 /* nachsehen, ob man selbst in der Triangulierung drin ist 00504 * wenn nicht: genau 2 nachbarn? -> dreieck einfügen 00505 * wenn sonst: nachricht versenden, nachbarn dreiecke suchen lassen 00506 */ 00507 template<typename OsModel_P, 00508 typename Radio_P, typename Distance_P, 00509 typename Debug_P> 00510 void 00511 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00512 complete_triangulation_timer_elapsed(void* userdata) { 00513 00514 #ifdef DEBUG_TRIANGULATION 00515 debug().debug( "complete_triangulation_timer \n"); 00516 #endif 00517 00518 if(!nodeInTriangles()) { 00519 #ifdef DEBUG_TRIANGULATION 00520 debug().debug( "nicht in triangles: %i \n", radio().id()); 00521 #endif 00522 00523 for(int i=0;i<NODECOUNT;i++) { 00524 if(distances[i] != 0) neighbourCount++; 00525 } 00526 00527 if(neighbourCount == 2) { 00528 int neighbour_indices[2] = {-1,-1}; 00529 for(unsigned int i=0; i<neighbourMap.size(); i++) { 00530 if(distances[i] != 0) { 00531 if(neighbour_indices[0] == -1) neighbour_indices[0] = i; 00532 else neighbour_indices[1]=i; 00533 } 00534 } 00535 00536 if(getNode(neighbour_indices[0]) < getNode(neighbour_indices[1])) 00537 setTriangleGlobal(radio().id(),getNode(neighbour_indices[0]),getNode(neighbour_indices[1]),2); 00538 else setTriangleGlobal(radio().id(),getNode(neighbour_indices[1]),getNode(neighbour_indices[0]),2); 00539 00540 #ifdef DEBUG_TRIANGULATION 00541 debug().debug( "2 nachbarn, dreieck eingefuegt \n"); 00542 #endif 00543 } 00544 else { //nicht genau 2 nachbarn 00545 Message message; 00546 message.set_msg_id(ASKFORCIRCLE); 00547 message.destination = radio().BROADCAST_ADDRESS; 00548 //radio().send(radio().BROADCAST_ADDRESS,message.buffer_size(), (block_data_t*)&message); 00549 00550 messages.push_back(message); 00551 millis_t random = rand(); 00552 random = random % MILLIS; 00553 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 00554 00555 demandedCircleIDs[2] = -1; 00556 } 00557 00558 timer().template set_timer<self_type, &self_type::select_best_circle_timer_elapsed>( waitingTime2, this, 0 ); 00559 } 00560 00561 //*in* triangles, auswertung starten, und doppelte zeit warten (select_best überspringen) 00562 else { 00563 timer().template set_timer<self_type, &self_type::fourth_timer_elapsed>( waitingTime2+waitingTime2, this, 0); 00564 } 00565 } 00566 00567 /* Auswerten der Ergebnisse von Vorschlägen für Kreise 00568 * 00569 */ 00570 template<typename OsModel_P, 00571 typename Radio_P, typename Distance_P, 00572 typename Debug_P> 00573 void 00574 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00575 select_best_circle_timer_elapsed (void* userdata) { 00576 00577 //für Auswertung 00578 timer().template set_timer<self_type, &self_type::fourth_timer_elapsed>( waitingTime2, this, 0); 00579 00580 node_id_t selfID = radio().id(); 00581 00582 //keine Antwort von Nachbarn, dann selbst suchen 00583 if(demandedCircleIDs[2] == -1) { 00584 #ifdef DEBUG_TRIANGULATION 00585 debug().debug( "keine antwort, eigener bestCircle \n"); 00586 #endif 00587 int index = bestCircleIndex(selfID); 00588 if(index>=0) { 00589 setTriangleGlobal(selfID,foundCircles[index].idFirst,foundCircles[index].idSecond, lookUpTrust(foundCircles[index].ratingFirst, foundCircles[index].ratingSecond)); 00590 00591 #ifdef DEBUG_TRIANGULATION 00592 debug().debug( "Rating: %i %i \n",foundCircles[index].ratingFirst,foundCircles[index].ratingSecond); 00593 debug().debug( "IDs: %i %i \n", foundCircles[index].idFirst, foundCircles[index].idSecond); 00594 #endif 00595 00596 } 00597 } 00598 //knoten noch ohne anschluss, hat aber vorschläge erhalten 00599 else if(demandedCircleIDs[2] != -1 && demandedCircleIDs[2] != 0) { 00600 00601 #ifdef DEBUG_TRIANGULATION 00602 debug().debug( "Kreisvorschlag mit Trust: %i \n", demandedCircleIDs[2]); 00603 debug().debug( "IDs: %i und %i \n", demandedCircleIDs[0],demandedCircleIDs[1]); 00604 #endif 00605 00606 //prüfen, ob ein eigener kreis besser ist als der vorgeschlagene 00607 int index = bestCircleIndex(selfID); 00608 if(lookUpTrust(foundCircles[index].ratingFirst, foundCircles[index].ratingSecond) < demandedCircleIDs[2]) 00609 setTriangleGlobal(selfID,foundCircles[index].idFirst,foundCircles[index].idSecond, lookUpTrust(foundCircles[index].ratingFirst, foundCircles[index].ratingSecond)); 00610 else 00611 setTriangleGlobal(selfID,demandedCircleIDs[0],demandedCircleIDs[1],demandedCircleIDs[2]); 00612 } 00613 } 00614 00615 template<typename OsModel_P, 00616 typename Radio_P, typename Distance_P, 00617 typename Debug_P> 00618 void 00619 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00620 fourth_timer_elapsed (void* userdata) { 00621 00622 #ifdef DEBUG_TRIANGULATION 00623 debug().debug( "distances-array: \n"); 00624 for(int i=0;i<NODECOUNT;i++) { 00625 if(distances[i] != 0) { 00626 debug().debug( "distance[%i]: %i (node %i) \n",i,(int)distances[i],getNode(i)); 00627 } 00628 } 00629 00630 debug().debug( "ndistances: \n"); 00631 for(int i=0;i<NODECOUNT;i++) { 00632 for(int j=0; j<NODECOUNT; j++) { 00633 if(ndistances[i][j] != 0) { 00634 debug().debug( "ndistances[%i][%i]: %i \n", i,j,(int)ndistances[i][j]); 00635 } 00636 } 00637 } 00638 00639 debug().debug("messages.size()=%i \n", messages.size()); 00640 00641 debug().debug( "foundCircles.size()=%i \n", foundCircles.size()); 00642 debug().debug( "triangles.size()=%i \n", triangles.size()); 00643 00644 for(int i=0;i<foundCircles.size();i++) { 00645 debug().debug( "foundCircles[%i].idFirst = %i, idSecond = %i \n",i,foundCircles[i].idFirst, foundCircles[i].idSecond); 00646 debug().debug( "foundCircles[%i].ratingFirst = %i, ratingSecond = %i \n", i, (int)foundCircles[i].ratingFirst, (int)foundCircles[i].ratingSecond); 00647 } 00648 00649 for(int i=0;i<triangles.size();i++) { 00650 debug().debug( "triangles[%i].idFirst = %i, idSecond = %i,idThird=%i \n",i,triangles[i].idFirst, triangles[i].idSecond, triangles[i].idThird); 00651 } 00652 #endif 00653 00654 } 00655 00656 template<typename OsModel_P, 00657 typename Radio_P, typename Distance_P, 00658 typename Debug_P> 00659 void 00660 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00661 message_timer_elapsed (void* userdata) { 00662 00663 Message message; 00664 message = messages[0]; 00665 node_id_t destination = messages[0].destination; 00666 radio().send(destination,message.buffer_size(),(block_data_t*)&message); 00667 debug().debug("msg sent->%i - id:%i \n", (int)destination, (int)messages[0].msg_id()); 00668 messages.erase(messages.begin()); 00669 00670 } 00671 00672 00673 template<typename OsModel_P, 00674 typename Radio_P, typename Distance_P, 00675 typename Debug_P> 00676 void 00677 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00678 send_timer_elapsed (void* userdata) { 00679 00680 #ifdef DEBUG_TRIANGULATION 00681 //debug().debug( "send_timer elapsed, rufe send() auf \n"); 00682 #endif 00683 00684 send_timer_running = 0; 00685 if(coordinates_called = true && send_timer_running == 0) { 00686 timer().template set_timer<self_type, &self_type::send_timer_elapsed>( 500, this, 0); 00687 send_timer_running = 1; 00688 } 00689 00690 send(); 00691 } 00692 // ----------------------------------------------------------------------- 00693 00694 /*template<typename OsModel_P, 00695 typename Radio_P, typename Distance_P, 00696 typename Debug_P> 00697 void Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>::reset_data() { 00698 00699 send_called = false; 00700 p_index = -1; 00701 q_index = -1; 00702 neighbourCount = 0; 00703 neighbourMap.clear(); 00704 foundCircles.clear(); 00705 triangles.clear(); 00706 00707 }*/ 00708 00709 // ----------------------------------------------------------------------- 00710 template<typename OsModel_P, 00711 typename Radio_P, typename Distance_P, 00712 typename Debug_P> 00713 int Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>::max(int a, int b) { 00714 return (a>b?a:b); 00715 } 00716 00717 template<typename OsModel_P, 00718 typename Radio_P, typename Distance_P, 00719 typename Debug_P> 00720 int Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>::min(int a, int b) { 00721 return (a<b?a:b); 00722 00723 } 00724 00725 template<typename OsModel_P, 00726 typename Radio_P, typename Distance_P, 00727 typename Debug_P> 00728 void 00729 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00730 findP() { 00731 00732 #ifdef DEBUG_TRIANGULATION 00733 debug().debug( "findP \n"); 00734 #endif 00735 00736 //Sucht einen Knoten, der möglichst viele der eigenen Nachbarn erreicht 00737 int commonNeighbours = 0; 00738 int commonNeighboursBest = 0; 00739 node_id_t nodesID_index = 0; 00740 00741 //Gehe gesamte Matrix durch 00742 for(int i=0;i<NODECOUNT;i++) { 00743 00744 //Zwischenspeichern des besten Ergebnisses 00745 if(commonNeighboursBest < commonNeighbours) { 00746 commonNeighboursBest = commonNeighbours; 00747 nodesID_index = i-1; 00748 } 00749 00750 //Gleichheit der Ergebnisse -> zufällig q tauschen 00751 /* if(commonNeighboursBest == commonNeighbours) { 00752 double random1 = rand()%10; //random1 von 0..9 00753 if(random1<4) { //random1 in 0..3 ? Tauschen 00754 nodesID_index = i-1; 00755 } 00756 }*/ 00757 00758 //Zurücksetzen der hilfsvariablen 00759 commonNeighbours = 0; 00760 00761 if(distances[i] == 0 || i==getIndex(radio().id())) {} //geprüfter knoten muss nachbar sein 00762 else { 00763 for(int j=0;j<NODECOUNT;j++) { 00764 if(ndistances[i][j] != 0 //geprüfter knoten hat einen nachbarn .. 00765 && distances[j] != 0 //den man auch selber sieht 00766 && i != j //nachbar des knotens ist er nicht selbst 00767 //&& j !=getIndex(radio().id())) //nachbar ist man auch nicht selbst 00768 &&j != 0) //nachbar ist man nicht selber - man steht auf index 0 00769 { 00770 commonNeighbours++; 00771 } //if 00772 } //for j 00773 } //else 00774 } //for i 00775 00776 //p setzen, q wählen 00777 //q so wählen, dass q sein gamma in {-1,1} liegt 00778 if(commonNeighboursBest >0 ) { 00779 p_index= nodesID_index; 00780 q_index= -1; 00781 for(int c=0;c<NODECOUNT;c++) { 00782 00783 //prüfen, ob c als potenzielles q infrage kommt - gamma muss zwischen -1 und 1 sein 00784 float dip = distances[p_index]; 00785 float diq = distances[c]; 00786 float dpq = ndistances[p_index][c]; 00787 double gammaValue = ((diq*diq) + (dip*dip) - (dpq*dpq)) / (2*diq*dip); 00788 00789 //prüfen, ob Knoten p Knoten c sieht, und ob gamma passt 00790 if(ndistances[p_index][c] != 0 && -1 <= gammaValue && gammaValue <= 1) { 00791 //if(q_index==-1) 00792 q_index=c; 00793 /* double r = rand() % 10; 00794 if(r<4) q_index=c;*/ 00795 } 00796 } 00797 } 00798 else {p_index=-1;q_index=-1;} 00799 00800 // debug().debug( "p_index: %i->Node %i, q_index: %i->Node %i \n", p_index, getNode(p_index), q_index, getNode(q_index)); 00801 00802 if(p_index!=-1 && q_index!= -1 && coordinates[p_index][1] == 0 && coordinates[q_index][0] == 0 && coordinates[q_index][1] == 0) { 00803 findCoordinatesP(); 00804 } 00805 00806 } 00807 00808 00809 template<typename OsModel_P, 00810 typename Radio_P, typename Distance_P, 00811 typename Debug_P> 00812 void 00813 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00814 findCoordinatesP() { 00815 00816 #ifdef DEBUG_TRIANGULATION 00817 debug().debug( "findCoordinatesP \n" ); 00818 #endif 00819 00820 int selfIndex = getIndex(radio().id()); 00821 coordinates[selfIndex][0] = 0; //eigenes x: 0 00822 coordinates[selfIndex][1] = 0; //eigenes y: 0 00823 coordinates[p_index][0] = distances[p_index]; //p: x entspricht abstand 00824 coordinates[p_index][1] = 0; //p: auf x-achse 00825 00826 //q-koordinaten 00827 // double gamma = 0.0; 00828 double dip = distances[p_index]; //distanz i->p 00829 double diq = distances[q_index]; //distanz i->q 00830 double dpq = ndistances[p_index][q_index]; //distanz p->q 00831 double gammaValue = ((diq*diq) + (dip*dip) - (dpq*dpq)) / (2*diq*dip); 00832 // gamma = acos(gammaValue); 00833 // coordinates[q_index][0] = diq * (cos(gamma)); 00834 // coordinates[q_index][1] = diq * (sin(gamma)); 00835 coordinates[q_index][0] = diq * (gammaValue); //cos(arccos(x)) = x 00836 coordinates[q_index][1] = diq * sqrt(1-(gammaValue*gammaValue)); //sin(arccos(x)) = sqrt(1-x*x) 00837 00838 //weitere Knoten 00839 // double alpha = 0.0; 00840 00841 for(int j=0;j<NODECOUNT;j++) { 00842 if(ndistances[p_index][j] != 0 //p hat j als nachbarn 00843 && distances[j] != 0 //knoten sieht j auch 00844 && j != selfIndex //j ist man auch nicht selber 00845 && j != p_index //j ist auch nicht p 00846 && j != q_index) //und auch nicht q 00847 { 00848 float dij = distances[j]; //distanz i->j 00849 float dpj = ndistances[p_index][j]; //distanz p->j 00850 double alphaValue = ((dij*dij) + (dip*dip) - (dpj*dpj)) / (2*dij*dip); 00851 if(-1 <= alphaValue && alphaValue <= 1) { 00852 // alpha = acos(alphaValue); 00853 // coordinates[j][0] = dij * (cos(alpha)); //x-koordinate von knoten j 00854 //betrag der y-koordinate von j ... 00855 // coordinates[j][1] = dij * (sin(alpha)); 00856 00857 coordinates[j][0] = dij * alphaValue; 00858 coordinates[j][1] = dij * sqrt(1-(alphaValue*alphaValue)); 00859 00860 //Distanz von q zu beiden möglichen y-koordinaten: y1 = positiv, y2=negativ 00861 00862 double x = (coordinates[q_index][0] - coordinates[j][0])*(coordinates[q_index][0] - coordinates[j][0]); //(x-x0)*(x-x0) 00863 double y1 =(coordinates[q_index][1] - coordinates[j][1])*(coordinates[q_index][1] - coordinates[j][1]); //(y-y1)*(y-y1) 00864 double y2 =(coordinates[q_index][1] + coordinates[j][1])*(coordinates[q_index][1] + coordinates[j][1]); //(y-y2)*(y-y2) 00865 00866 double dqjCS1 = sqrt(x + y1); //berechnete Distanz q->j mit j positiv 00867 double dqjCS2 = sqrt(x + y2); //berechnete Distanz q->j mit j negativ 00868 00869 if(ndistances[q_index][j] != 0) { 00870 //für schwankende abstände 00871 double diffPos = fabs(ndistances[q_index][j] - dqjCS1); //Differenzbetrag Messung & Berechnung für j positiv 00872 double diffNeg = fabs(ndistances[q_index][j] - dqjCS2); //Differenzbetrag Messung & Berechnung für j negativ 00873 if(diffPos < diffNeg) {} //j bleibt positiv 00874 else if(diffPos > diffNeg) {coordinates[j][1] = -(coordinates[j][1]);} //j wird negativ 00875 } 00876 else { //Distanz q->j gibts nicht, d.h. j ganz weit weg 00877 if(coordinates[q_index][1] > 0) //q über der x-Achse .. 00878 coordinates[j][1] = -(coordinates[j][1]); //dann ist j drunter 00879 //else implizit behandelt 00880 } //else 00881 } // if alpha 00882 } // if knoten hinzufügbar 00883 } // for j 00884 00885 } //Funktion 00886 00887 template<typename OsModel_P, 00888 typename Radio_P, typename Distance_P, 00889 typename Debug_P> 00890 void 00891 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00892 findPQ() { 00893 00894 int pq[3]; //0: P, 1: Q, 2: Score 00895 pq[2] = 0; pq[1] = -1; pq[0] = -1; 00896 int pqBest[3]; 00897 pqBest[2] = 0; pqBest[1] = -1; pqBest[0] = -1; 00898 00899 for(int i=0; i<NODECOUNT; i++) { 00900 00901 //beste pq-Kombi speichern 00902 if(pqBest[2] < pq[2]) { 00903 pqBest[0] = pq[0]; 00904 pqBest[1] = pq[1]; 00905 pqBest[2] = pq[2]; 00906 } 00907 /* if(pqBest[2] == pq[2]) { 00908 double random1 = rand()%10; //random1 von 0..9 00909 if(random1<4) { //random1 in 0..3 ? Tauschen 00910 pqBest[0] = pq[0]; 00911 pqBest[1] = pq[1]; 00912 pqBest[2] = pq[2]; 00913 } 00914 }*/ 00915 00916 00917 if(distances[i] != 0 && i!=getIndex(radio().id())) { // Knoten sieht p 00918 for(int j=0; j<neighbourMap.size(); j++) { 00919 if(ndistances[i][j] != 0 && distances[j] != 0 && getNode(i)!=getNode(j)) { //q nachbar von p?, knoten sieht q?, p != q? 00920 pq[0] = i; //Setze i=p 00921 pq[1] = j; //Setze j=q 00922 pq[2] = 0; //Score auf 0 00923 00924 //Gamma testen, ob innerhalb (-1,1) 00925 float dip = distances[i]; //distanz i->p 00926 float diq = distances[j]; //distanz i->q 00927 float dpq = ndistances[i][j]; //distanz p->q 00928 double gammaValue = ((diq*diq) + (dip*dip) - (dpq*dpq)) / (2*diq*dip); 00929 00930 if(-1 <= gammaValue && gammaValue <= 1) { 00931 //jetzt prüfen, wieviele Nachbarn p und q gemein haben 00932 for(int k=0;k<neighbourMap.size();k++) { 00933 if(ndistances[pq[0]][k] != 0 //p sieht k 00934 && ndistances[pq[1]][k] != 0 //q sieht k 00935 && distances[k] != 0 //knoten sieht k auch 00936 && pq[0] != k //p != k 00937 && pq[1] != k //q != k 00938 && getIndex(radio().id()) != k) //k ist nicht der Knoten selbst 00939 { 00940 int scoreTemp = pq[2]; 00941 scoreTemp++; 00942 pq[2] = scoreTemp; 00943 } //if 00944 } //for k 00945 } //if 00946 } //if 00947 } // for j 00948 } //if 00949 } // for i 00950 00951 if(pqBest[2] > 0) { 00952 p_index= pqBest[0]; 00953 q_index= pqBest[1]; 00954 debug().debug( "p und q gesetzt bei Knoten %i \n", radio().id()); 00955 00956 if(coordinates[p_index][1] == 0 && coordinates[q_index][0] == 0 && coordinates[q_index][1] == 0) { 00957 findCoordinatesPQ(); 00958 debug().debug("aufruf findCoordinatesPQ bei Knoten %i \n",radio().id()); 00959 } 00960 00961 } 00962 00963 } //Funktion 00964 00965 template<typename OsModel_P, 00966 typename Radio_P, typename Distance_P, 00967 typename Debug_P> 00968 void 00969 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 00970 findCoordinatesPQ() { 00971 00972 int self = getIndex(radio().id()); 00973 coordinates[self][0] = 0; //eigenes x: 0 00974 coordinates[self][1] = 0; //eigenes y: 0 00975 00976 coordinates[p_index][0] = distances[p_index]; //p: x entspricht abstand 00977 coordinates[p_index][1] = 0; //p: auf x-achse 00978 00979 //q-koordinaten 00980 double gamma = 0.0; 00981 float dip = distances[p_index]; //distanz i->p 00982 float diq = distances[q_index]; //distanz i->q 00983 float dpq = ndistances[p_index][q_index]; //distanz p->q 00984 double gammaValue = ((diq*diq) + (dip*dip) - (dpq*dpq)) / (2*diq*dip); 00985 gamma = acos(gammaValue); 00986 coordinates[q_index][0] = diq * (cos(gamma)); 00987 coordinates[q_index][1] = diq * (sin(gamma)); 00988 00989 //für weitere knoten j: 00990 double alpha = 0.0; 00991 double beta = 0.0; 00992 00993 for(int j=0;j<NODECOUNT;j++) { 00994 if(ndistances[p_index][j] != 0 //p hat j als nachbarn 00995 && ndistances[q_index][j] != 0 //q auch 00996 && distances[j] != 0 //knoten sieht j auch 00997 && j != self //j ist man auch nicht selber 00998 && j != p_index //j ist auch nicht p 00999 && j != q_index) //und auch nicht q 01000 { 01001 float dij = distances[j]; //distanz i->j 01002 float dpj = ndistances[p_index][j]; //distanz p->j 01003 float dqj = ndistances[q_index][j]; //distanz q->j 01004 double alphaValue = ((dij*dij) + (dip*dip) - (dpj*dpj)) / (2*dij*dip); 01005 double betaValue = ((diq*diq) + (dij*dij) - (dqj*dqj)) / (2*diq*dij); 01006 if(-1 <= betaValue && betaValue <= 1 && -1 <= alphaValue && alphaValue <= 1) { 01007 alpha = acos(alphaValue); 01008 beta = acos(betaValue); 01009 coordinates[j][0] = dij * (cos(alpha)); //x-koordinate von knoten j 01010 //betrag der y-koordinate von j ... 01011 coordinates[j][1] = dij * (sin(alpha)); 01012 //über oder unter x-achse? Toleranzbereich: 01013 double diffGammaAlpha = fabs(alpha-gamma); 01014 double tolerance = 0.6; //TODO: Toleranzwert 01015 if( (diffGammaAlpha-tolerance) <= beta && beta <= (diffGammaAlpha+tolerance) ) {} //beta im tol-bereich von |alpha-gamma| -> y bleibt positiv 01016 else coordinates[j][1] = -(coordinates[j][1]); //sonst: y wird negativ 01017 } 01018 } 01019 } 01020 01021 } //Funktion 01022 01023 01024 01031 template<typename OsModel_P, 01032 typename Radio_P, typename Distance_P, 01033 typename Debug_P> 01034 void 01035 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01036 findCircle() { 01037 01038 #ifdef DEBUG_TRIANGULATION 01039 debug().debug( "findCircle() \n"); 01040 #endif 01041 01042 01043 for(int i=0;i<NODECOUNT;i++) { //Distanz-Array durchgehen 01044 if(distances[i] != 0) { //wenn Nachbar i existiert 01045 for(int j=0; j<neighbourMap.size(); j++) { //gehe alle seine Nachbarn durch 01046 if( ndistances[i][j] != 0 //wenn i einen Nachbarn j hat.. 01047 && i != j //und j nicht i ist 01048 && (coordinates[i][0] != 0 || coordinates[i][1] != 0) //und es zu i Koordinaten gibt 01049 && (coordinates[j][0] != 0 || coordinates[j][1] != 0) //und zu j auch 01050 ) 01051 { 01052 int testResult = testCircle(i,j); 01053 01054 if(testResult == 1) { 01055 circle c; 01056 01057 if(getNode(i) < getNode(j)) { 01058 c.idFirst = getNode(i); 01059 c.idSecond = getNode(j); 01060 } 01061 else { 01062 c.idFirst = getNode(j); 01063 c.idSecond = getNode(i); 01064 } 01065 c.ratingFirst = -1; //-1 kommt bei der Bewertung nicht vor, gibt nur 0,1,2 01066 c.ratingSecond = -1; 01067 01068 for(unsigned int a=0; a<NODECOUNT; a++) { 01069 if(foundCircles[a].idFirst == min(getNode(i),getNode(j)) 01070 && foundCircles[a].idSecond == max(getNode(i),getNode(j)) ) { 01071 break; 01072 } 01073 else if(a==NODECOUNT-1) { //gefundener Kreis noch nicht eingetragen 01074 foundCircles.push_back(c); 01075 //prüfen lassen, nachricht senden 01076 Message msg; 01077 msg.set_msg_id(CHECK_CIRCLE); 01078 msg.set_node_id(getNode(j)); 01079 //radio().send(getNode(i),msg.buffer_size(),(uint8_t*)&msg); 01080 // debug().debug("checkcircle->%i \n",(int)getNode(i)); 01081 01082 msg.destination = getNode(i); 01083 messages.push_back(msg); 01084 millis_t random = rand(); 01085 random = random % MILLIS; 01086 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( 800+random ,this , 0 ); 01087 01088 msg.set_node_id(getNode(i)); 01089 01090 // radio().send(getNode(j),msg.buffer_size(),(uint8_t*)&msg); 01091 // debug().debug( "checkcircle->%i \n", (int)getNode(j)); 01092 01093 msg.destination = getNode(j); 01094 messages.push_back(msg); 01095 random = rand(); 01096 random = random % MILLIS; 01097 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 01098 } 01099 } 01100 } 01101 } 01102 } 01103 } 01104 } 01105 01106 } 01107 01108 01115 template<typename OsModel_P, 01116 typename Radio_P, typename Distance_P, 01117 typename Debug_P> 01118 int 01119 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01120 testCircle(int B, int C) { 01121 //1 für: Kreis passt, 2 für: Kreis passt nicht, 0 für: Punkte keine Nachbarn 01122 01123 int self = getIndex(radio().id()); 01124 float xA = coordinates[self][0]; //0 01125 float yA = coordinates[self][1]; //0 01126 float xB = 0; 01127 float yB = 0; 01128 float xC = 0; 01129 float yC = 0; 01130 float x1 = 0; 01131 float y1 = 0; 01132 float x2 = 0; 01133 float y2 = 0; 01134 float x3 = 0; 01135 float y3 = 0; 01136 01137 01138 if(coordinates[B][0] != 0 || coordinates[B][1] != 0) { //Prüfen ob Koordinaten vorhanden 01139 xB = coordinates[B][0]; 01140 yB = coordinates[B][1]; 01141 } 01142 else { 01143 return 0; 01144 } 01145 01146 if(coordinates[C][0] != 0 || coordinates[C][1] != 0) { //Prüfen ob Koordinaten vorhanden 01147 xC = coordinates[C][0]; 01148 yC = coordinates[C][1]; 01149 } 01150 else { 01151 return 0; 01152 } 01153 01154 01155 //Schnitt 2er Mittelsenkrechten 01156 int nullCount = 0; 01157 float yAB = yA-yB; if(yAB == 0) nullCount++; 01158 float yAC = yA-yC; if(yAC == 0) nullCount++; 01159 float yBC = yB-yC; if(yBC == 0) nullCount++; 01160 01161 01162 if(nullCount >1) { 01163 return 0; 01164 #ifdef DEBUG_TRIANGULATION 01165 debug().debug( "zu oft null \n"); 01166 #endif 01167 } //keine berechnung möglich weil nenner 2 mal 0 - rückgabe 0 oder 2 ? 01168 if(nullCount == 0 || yAC==0) {x1 = xA; y1 = yA; x2 = xB; y2 = yB; x3 = xC; y3= yC;} //AB & BC 01169 if(yBC==0) {x1 = xC; y1 = yC; x2 = xA; y2 = yA; x3 = xB; y3= yB;} //AC + AB <=> CA & AB 01170 if(yAB==0) {x1 = xA; y1 = yA; x2 = xC; y2 = yC; x3 = xB; y3= yB;} //AC + BC <=> AC & CB 01171 01172 01173 //Werte für Mittelsenkrechte 1 01174 //y = -(xA-xB)/(yA-yB) * x + xA^2 - xB^2 + yA^2 - yB^2 / 2(yA-yB) 01175 double m1first = (x1-x2) / (y1-y2); 01176 if((y1-y2) == 0){ 01177 #ifdef DEBUG_TRIANGULATION 01178 debug().debug( "y1-y2 ist 0; y1 ist %i und y2 ist %i \n",y1,y2); 01179 #endif 01180 } 01181 m1first = (-1) * m1first; 01182 double m1secondZ = (x1*x1) - (x2*x2) + (y1*y1) - (y2*y2); 01183 double m1secondN = 2*(y1-y2); 01184 double m1second = m1secondZ / m1secondN; 01185 01186 //Werte für Mittelsenkrechte 2 01187 double m2first = (x2-x3)/(y2-y3); 01188 if((y2-y3) == 0) { 01189 #ifdef DEBUG_TRIANGULATION 01190 debug().debug( "y2-y3 ist 0; y2 ist %i und y3 ist %i \n",y2,y3); 01191 #endif 01192 } 01193 m2first = (-1) * m2first; 01194 double m2secondZ = (x2*x2) - (x3*x3) + (y2*y2) - (y3*y3); 01195 double m2secondN = 2*(y2-y3); 01196 double m2second = m2secondZ / m2secondN; 01197 01198 //Kreismitte mit x und y 01199 double m1fmm2f = m1first - m2first; //m1-m2 01200 if(m1fmm2f == 0) {} 01201 double m2smm1s = m2second - m1second; //n2-n1 01202 double x = m2smm1s / m1fmm2f; //x = ... 01203 double y = (m1first * x) + m1second; //x einsetzen -> y= ... 01204 double r2 = sqrt((x2-x)*(x2-x) + (y2-y)*(y2-y)); //Radius des Kreises = Abstand Ursprung zur Mitte 01205 01206 01207 //Prüfen, ob Dealaunay-Dreieck 01208 for(int k=0;k<NODECOUNT;k++) { //alle Nachbarn durchgehen 01209 if((coordinates[k][0] !=0 || coordinates[k][1] != 0) //Koordinaten für k vorhanden 01210 && k != self //ausschließen aller mitglieder des dreiecks 01211 && k != B 01212 && k != C) { 01213 float testX = coordinates[k][0]; 01214 float testY = coordinates[k][1]; 01215 01216 //Abstand zur Kreismitte 01217 double distR = sqrt(((testX-x)*(testX-x)) + ((testY-y)*(testY-y))); //Distanz zur Kreismitte 01218 if(distR < r2) { 01219 return 2; 01220 } 01221 } 01222 } 01223 return 1; 01224 } 01225 01226 template<typename OsModel_P, 01227 typename Radio_P, typename Distance_P, 01228 typename Debug_P> 01229 void 01230 Triangulation<OsModel_P,Radio_P, Distance_P, Debug_P>:: 01231 setRating(node_id_t fromID, node_id_t thirdID, int rating) 01232 { 01233 int self = (int)getIndex(radio().id()); 01234 01235 // debug().debug("setRating mit %i,%i,%i \n", (int)fromID,(int)thirdID,(int)rating); 01236 // debug().debug( "setRating \n"); 01237 01238 for(int i=0; i<=(int)foundCircles.size(); i++) { 01239 01240 // debug().debug( "for-schleife in setRating \n"); 01241 // debug().debug( "pruefe, ob %i oder %i zu aufruf passen \n", (int)foundCircles[i].idFirst, (int)foundCircles[i].idSecond); 01242 // debug().debug( "undzwar zu %i und %i \n", min(fromID,thirdID),max(fromID,thirdID)); 01243 01244 01245 if((int)foundCircles[i].idFirst == min(fromID,thirdID) 01246 && (int)foundCircles[i].idSecond == max(fromID, thirdID)) 01247 { 01248 01249 // debug().debug( "kreis gefunden in setRating \n"); 01250 01251 if((int)fromID == (int)foundCircles[i].idFirst) { 01252 debug().debug( "set ratingFirst \n"); 01253 foundCircles[i].ratingFirst = rating; 01254 } 01255 else if((int)fromID == (int)foundCircles[i].idSecond) { 01256 debug().debug( "set ratingSecond \n"); 01257 foundCircles[i].ratingSecond = rating; 01258 } 01259 01260 if(foundCircles[i].ratingFirst == 1 01261 && foundCircles[i].ratingSecond == 1) { 01262 //in globale Triangulierung eintragen 01263 debug().debug("triangleglobal aus setrating: %i %i %i",getNode(self),foundCircles[i].idFirst, foundCircles[i].idSecond); 01264 //setTriangleGlobal((int)getNode(self), (int)foundCircles[i].idFirst, (int)foundCircles[i].idSecond, 1); 01265 setTriangleGlobal(getNode(self),foundCircles[i].idFirst, foundCircles[i].idSecond, 1); 01266 break; 01267 } 01268 if((foundCircles[i].ratingFirst == 1 && foundCircles[i].ratingSecond == 0) // einer stimmt zu, der andere sieht zuwenig 01269 || (foundCircles[i].ratingFirst == 0 && foundCircles[i].ratingSecond == 1)) // und umgedreht 01270 { 01271 debug().debug("1 1 0 \n"); 01272 setTriangleGlobal((int)getNode(self), (int)foundCircles[i].idFirst, (int)foundCircles[i].idSecond, 2); 01273 break; 01274 } 01275 } 01276 } 01277 } 01278 01279 template<typename OsModel_P, 01280 typename Radio_P, typename Distance_P, 01281 typename Debug_P> 01282 void 01283 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01284 setTriangleGlobal(node_id_t a, node_id_t b, node_id_t c, int trust) { 01285 01287 01288 //debug().debug("triangleglobal mit %i, %i, %i \n", a,b,c); 01289 01290 triangle t; 01291 t.trust = trust; 01292 01293 if(a<b) { 01294 t.idFirst = a; 01295 t.idSecond = b; 01296 t.idThird = c; 01297 } 01298 else if(b < a && a < c) { 01299 t.idFirst = b; 01300 t.idSecond = a; 01301 t.idThird = c; 01302 } 01303 else { 01304 t.idFirst = b; 01305 t.idSecond = c; 01306 t.idThird = a; 01307 } 01308 01309 01310 //hinzufügen des dreiecks, falls noch nicht im vector enthalten 01311 //weitergeben der meldung an die nachbarn 01312 for(int i=0; i<VECTORSIZE; i++) { 01313 if(triangles[i].idFirst == a && triangles[i].idSecond == b && triangles[i].idThird == c) { //Dreieck enthalten? 01314 if(triangles[i].prop != true) { //noch nicht propagiert? 01315 Message message; //versenden ... 01316 message.set_msg_id(TRIANGLE_PROP); 01317 message.set_node_id(t.idFirst); 01318 message.set_seq_nr(t.idSecond); 01319 message.set_trust(t.trust); 01320 message.set_id(t.idThird); 01321 // radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message); 01322 01323 message.destination=radio().BROADCAST_ADDRESS; 01324 messages.push_back(message); 01325 millis_t random = rand(); 01326 random = random % MILLIS; 01327 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 01328 01329 triangles[i].prop = true; //als propagiert kennzeichnen 01330 } 01331 break; 01332 } 01333 else if(i==VECTORSIZE-1) { //Dreieck noch nicht enthalten 01334 t.prop = true; 01335 triangles.push_back(t); //einfügen und propagieren 01336 Message message; 01337 message.set_msg_id(TRIANGLE_PROP); 01338 message.set_node_id(t.idFirst); 01339 message.set_seq_nr(t.idSecond); 01340 message.set_trust(t.trust); 01341 message.set_id(t.idThird); 01342 // radio().send( radio().BROADCAST_ADDRESS, message.buffer_size(), (block_data_t*)&message); 01343 01344 message.destination = radio().BROADCAST_ADDRESS; 01345 messages.push_back(message); 01346 millis_t random = rand(); 01347 random = random % MILLIS; 01348 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 01349 01350 01351 } 01352 } 01353 } 01354 01355 template<typename OsModel_P, 01356 typename Radio_P, typename Distance_P, 01357 typename Debug_P> 01358 bool 01359 Triangulation<OsModel_P,Radio_P, Distance_P, Debug_P>:: 01360 nodeInTriangles() { 01361 for(unsigned int i=0; i<triangles.size();i++) { 01362 if(radio().id() == triangles[i].idFirst || radio().id() == triangles[i].idSecond || radio().id() == triangles[i].idThird) { 01363 return true; 01364 } 01365 } 01366 return false; 01367 } 01368 01369 template<typename OsModel_P, 01370 typename Radio_P, typename Distance_P, 01371 typename Debug_P> 01372 int 01373 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01374 bestCircleIndex(node_id_t demandedID) { 01375 if(demandedID == radio().id()) { 01376 int bestTrust = 20; 01377 int arrayIndex = -1; 01378 for(unsigned int j=0; j < foundCircles.size(); j++) { 01379 int t = lookUpTrust(foundCircles[j].ratingFirst, foundCircles[j].ratingSecond); 01380 if(t < bestTrust) { 01381 arrayIndex = j; 01382 bestTrust = t; 01383 } 01384 } 01385 return arrayIndex; 01386 } 01387 else { 01388 int bestTrust = 20; 01389 int arrayIndex = -1; 01390 for(unsigned int i=0; i<foundCircles.size();i++) { //alle kreise durchgehen 01391 if(demandedID == foundCircles[i].idFirst || demandedID == foundCircles[i].idSecond) { //einer der knoten ist der gesuchte 01392 int t = lookUpTrust(foundCircles[i].ratingFirst, foundCircles[i].ratingSecond); 01393 if(t < bestTrust) { 01394 arrayIndex = i; 01395 bestTrust = t; 01396 } 01397 } 01398 } 01399 return arrayIndex; 01400 } 01401 } 01402 01403 template<typename OsModel_P, 01404 typename Radio_P, typename Distance_P, 01405 typename Debug_P> 01406 int 01407 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01408 lookUpTrust(int ratingFirst, int ratingSecond) { 01409 01410 //1. 1-1-2 = 3 = gelb 01411 //2. 1-0-0 = 4 = orange 01412 //3. 1-0-2 = 5 = rot 01413 //4. 1-2-2 = 5 = rot 01414 01415 if((ratingFirst == 1 && ratingSecond == 2) || (ratingFirst == 2 && ratingSecond == 1)) { 01416 return 3; 01417 } 01418 if(ratingFirst == 0 && ratingSecond == 0) { 01419 return 4; 01420 } 01421 if((ratingFirst == 0 && ratingSecond == 2) || (ratingFirst == 2 && ratingSecond == 0)) { 01422 return 5; 01423 } 01424 if(ratingFirst == 2 && ratingSecond == 2) { 01425 return 5; 01426 } 01427 return 5; 01428 } 01429 01430 template<typename OsModel_P, 01431 typename Radio_P, 01432 typename Distance_P, 01433 typename Debug_P> 01434 void 01435 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01436 send() 01437 { 01438 Message msg; 01439 01440 01441 // if(!send_called) { 01442 01443 send_called = true; 01444 01445 if(send_timer_iteration != false) { 01446 msg.set_msg_id(DISTANCE_CHECK); 01447 radio().send( radio().BROADCAST_ADDRESS, msg.buffer_size(), (uint8_t*)&msg); 01448 } 01449 01450 01451 #ifdef DEBUG_TRIANGULATION 01452 // debug().debug( "aufruf send \n"); 01453 #endif 01454 01455 //timer aufrufen - wenn fertig, p und q suchen - bedingung: distanzen vollständig 01456 if(coordinates_timer_started == false) { 01457 timer().template set_timer<self_type, &self_type::coordinates_timer_elapsed>( waitingTime1, this, 0 ); 01458 coordinates_timer_started = true; 01459 } 01460 // } 01461 01462 } 01463 01464 01465 01466 // ----------------------------------------------------------------------- 01467 template<typename OsModel_P, 01468 typename Radio_P, typename Distance_P, 01469 typename Debug_P> 01470 void 01471 Triangulation<OsModel_P, Radio_P, Distance_P, Debug_P>:: 01472 receive( node_id_t from, size_t len, block_data_t *data ) 01473 { 01474 01475 if ( from == radio().id() ) 01476 return; 01477 01478 #ifdef DEBUG_TRIANGULATION 01479 debug().debug("msg<-%i \n",(int)from); 01480 #endif 01481 01482 double distance = dist_est_.distance(from); 01483 //double distance = 3; 01484 01485 Message* msgrec = (Message*) data; 01486 message_id_t msgID = msgrec->msg_id(); 01487 01488 //Distanz-Anfrage; sendet die Distanz an den anfragenden Knoten zurück 01489 if(msgID == DISTANCE_CHECK && send_timer_iteration != false) { 01490 01491 #ifdef DEBUG_TRIANGULATION 01492 debug().debug( "distance: %i \n",(int)distance); 01493 #endif 01494 01495 //Aufruf der Send-Methode, um den Knoten vor dem Timer zu "aktivieren" und die Timer relativ synchron zu starten 01496 if(send_called == false) send(); 01497 01498 if(distance>0) { 01499 Message message; 01500 message.set_msg_id(DISTANCE_RETURN); 01501 message.set_distance(distance); 01502 radio().send(from,message.buffer_size(),(block_data_t*)&message); 01503 } 01504 01505 if(distances[getIndex(from)] == 0 && distance > 0) { 01506 distances[getIndex(from)] = (float) distance; //Eintragen des Abstands 01507 // debug().debug( "distances zu %i war leer, beschrieben eben \n", from); 01508 } 01509 else if(distance > 0){ 01510 distances[getIndex(from)] = ((float)distance + distances[getIndex(from)]) / 2; 01511 //debug().debug( "distances zu %i war schon beschrieben, neuer wert: %i", from, (int) distances[getIndex(from)]); 01512 //den Mittelwert versenden 01513 Message message; 01514 message.set_msg_id(DISTANCE_PROP); 01515 message.set_distance(distances[getIndex(from)]); 01516 message.set_node_id(from); 01517 radio().send(radio().BROADCAST_ADDRESS,len,(block_data_t*)&message); 01518 } 01519 01520 } 01521 01522 //Antwort auf eine Distanzanfrage, in Array speichern 01523 else if(msgID == DISTANCE_RETURN && send_timer_iteration != false) { 01524 01525 double d = msgrec->distance(); 01526 01527 #ifdef DEBUG_TRIANGULATION 01528 // debug().debug( "node %i erhaelt distanz zurueck: %i ", radio().id(), (int)d); 01529 #endif 01530 01531 //Mittelwert aus eigener Messung (distances[from]) und der Messung d des Nachbarn 01532 if(distances[getIndex(from)] == 0) { 01533 distances[getIndex(from)] = d; 01534 // debug().debug( "distances zu %i war leer, beschrieben eben \n", from); 01535 } 01536 else { 01537 distances[getIndex(from)] = (d + distances[getIndex(from)]) / 2; 01538 // debug().debug( "distances zu %i war schon beschrieben, neuer wert: %i", from, (int) distances[getIndex(from)]); 01539 01540 01541 //den Mittelwert versenden 01542 Message message; 01543 message.set_msg_id(DISTANCE_PROP); 01544 message.set_node_id(from); 01545 message.set_distance(distances[getIndex(from)]); 01546 radio().send(radio().BROADCAST_ADDRESS,len,(block_data_t*)&message); 01547 } 01548 } 01549 01550 01551 //Verbreiten der Distanzmessung, in Gesamt-Array speichern 01552 else if(msgID == DISTANCE_PROP && send_timer_iteration != false) { 01553 01554 // debug().debug( "prop erhalten von %i \n", from); 01555 01556 node_id_t nodeID = msgrec->node_id(); 01557 ndistances[getIndex(from)][getIndex(nodeID)]= msgrec->distance(); 01558 } 01559 01560 //anforderung, einen kreis zu prüfen, mit absender und in node_id enthaltenen Knoten 01561 else if(msgID == CHECK_CIRCLE) { 01562 01563 Message message; 01564 01565 node_id_t nodeID = msgrec->node_id(); 01566 01567 // debug().debug( "check_circle von %i, kreis testen mit %i \n", (int)from, (int)nodeID); 01568 // debug().debug( "hole Index von nodeID: %i und von from: %i", (int)getIndex(nodeID), (int)getIndex(from)); 01569 01570 int testResult = testCircle(getIndex(nodeID),getIndex(from)); 01571 01572 message.set_node_id(nodeID); 01573 message.set_msg_id(CHECK_CIRCLE_RETURN); 01574 message.set_result(testResult); 01575 01576 message.destination = from; 01577 messages.push_back(message); 01578 millis_t random = rand(); 01579 random = random % MILLIS; 01580 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 01581 01582 // radio().send( from,message.buffer_size(), (block_data_t*)&message); 01583 // debug().debug( "result->%i \n", (int)from); 01584 } 01585 01586 else if(msgID == CHECK_CIRCLE_RETURN) { 01587 01588 int result = msgrec->result(); 01589 node_id_t nodeID = msgrec->node_id(); 01590 debug().debug( "received return<-%i", (int)from); 01591 setRating(from, nodeID, result); 01592 } 01593 01594 else if(msgID == TRIANGLE_PROP) { 01595 node_id_t a = msgrec->node_id(); 01596 node_id_t b = msgrec->seq_nr(); 01597 // int c = atoi((char*)msgrec->payload()); 01598 node_id_t c = msgrec->id(); 01599 int t = msgrec->trust(); 01600 debug().debug("triangle_prop: %i %i %i \n",a,b,c); 01601 setTriangleGlobal(a,b,c,t); 01602 } 01603 01604 else if(msgID == ASKFORCIRCLE) { 01605 int circleIndex = bestCircleIndex(from); 01606 if (circleIndex>-1) { 01607 Message message; 01608 message.set_msg_id(RETURN_CIRCLE); 01609 if(from != foundCircles[circleIndex].idFirst) 01610 message.set_node_id(foundCircles[circleIndex].idFirst); 01611 else message.set_node_id(foundCircles[circleIndex].idSecond); 01612 message.set_trust(lookUpTrust(foundCircles[circleIndex].ratingFirst,foundCircles[circleIndex].ratingSecond)); 01613 //radio().send(from,message.buffer_size(),(block_data_t*)&message); 01614 01615 messages.push_back(message); 01616 millis_t random = rand(); 01617 random = random % MILLIS; 01618 timer().template set_timer<self_type, &self_type::message_timer_elapsed>( random ,this , 0 ); 01619 } 01620 } 01621 01622 else if(msgID == RETURN_CIRCLE) { 01623 01624 //falls noch keinen kreisvorschlag erhalten oder ein neuer kreisvorschlag ist besser als der alte ... 01625 if(demandedCircleIDs[2] == -1 || demandedCircleIDs[2] > msgrec->trust()) { 01626 if(from < msgrec->node_id()) { 01627 demandedCircleIDs[0] = from; 01628 demandedCircleIDs[1] = msgrec->node_id(); 01629 } 01630 else { 01631 demandedCircleIDs[0] = msgrec->node_id(); 01632 demandedCircleIDs[1] = from; 01633 } 01634 demandedCircleIDs[2] = msgrec->trust(); 01635 } 01636 01637 } 01638 01639 } 01640 01641 } 01642 #endif