#include "server.hh" /******* Misc. very usefull functions *******/ /* Tronque le float "f" à "n" décimales et le retourne */ inline float round_float(float f, int n) { n = (int) pow((double) 10, (double) n) ; float f_dec = modff(f, &f) ; f_dec = floor(f_dec * n) / n ; return f + f_dec ; } /* Tronque le float "f" à 2 décimales et le retourne */ inline float round_float_2(float f) { return round_float(f, 2) ; } /* Explodes a string into substrings based on separator sep. Returns a string vector. */ inline vector explode(const string &input, const char &sep) { vector vs; string tmp; unsigned int i; for (i = 0 ; i < input.size() ; i++) if (input[i] == sep) { vs.push_back(tmp); tmp.clear(); } else { tmp.push_back(input[i]); } //Last entry, did not encounter a separator. vs.push_back(tmp); tmp.clear(); return vs; } /* Function to convert a string to an integer */ inline int string2int(const string &nb) { istringstream iss(nb); int tmp; iss >> tmp; return tmp; } /* Function to convert a string to an unsigned integer */ inline unsigned int string2uint(const string &nb) { istringstream iss(nb); unsigned int tmp; iss >> tmp; return tmp; } /* Function to convert a string to a float */ inline float string2float(const string &nb) { istringstream iss(nb); float tmp; iss >> tmp; return tmp; } /* Function extracts ints from string */ inline vector extractValues(string buff) { unsigned int ptr = 0; vector ret; string tmp_field; if (buff[buff.size()-1] != ';') buff.push_back(';'); while (ptr < buff.size()) { if (buff[ptr] != ';') tmp_field.push_back(buff[ptr]); else { ret.push_back(string2int(tmp_field)); tmp_field.clear(); } ptr++; } return ret; } inline vector extractReferencePointInfoFromBuffer(const string &buffer_in) { unsigned int i = 0; string tmp_field; vector ret; /* Extract coordinates */ /* x */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; // go after the ';' /* y */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; #ifndef FRED_CSV_FORMAT // Dans le format Fred, on n'a pas de coordonnée Z. /* z */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; #endif // FRED_CSV_FORMAT /* Extract direction (not used now) */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; #ifdef FRED_CSV_FORMAT /* Extract mac address */ while (buffer_in[i] != ';') { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); i++; /* Extract scan list */ while (i < buffer_in.size()) { tmp_field.push_back(buffer_in[i]); i++; } ret.push_back(tmp_field); tmp_field.clear(); #else // FRED_CSV_FORMAT while (i <= buffer_in.size()) { if ((buffer_in[i] == ';' || i == buffer_in.size()) && !tmp_field.empty()) // Si on est sur un séparateur et que la valeur lue n'est pas vide, { #ifdef DEBUG_2 cout << "Ajout de la valeur lue : " << tmp_field << endl ; #endif // DEBUG_2 ret.push_back(tmp_field) ; // on met la valeur lue dans les valeurs de retour. tmp_field.clear() ; } else // Si on n'est pas sur un séparateur, tmp_field.push_back(buffer_in[i]) ; // on ajoute le caractère courant à la suite de la valeur lue. i++ ; } #endif // FRED_CSV_FORMAT /* Return the vector with each data */ return ret; } /* ***************************************************************** */ //Server::Server(string ip_addr, int listen_port, int send_port) // FIXME : paramètre send_port inutilisé Server::Server(const string &ap_file, const string &ref_pt_file, const string &ip_addr, const int &listen_port) { #ifdef DEBUG_T cout << "//--> Server::Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Open socket */ sockListen = socket(PF_INET, SOCK_DGRAM, 0); sockSend = socket(PF_INET, SOCK_DGRAM, 0); /* Set addr */ server_addr.sin_family = AF_INET; server_addr.sin_port = htons(listen_port); server_addr.sin_addr.s_addr = inet_addr(ip_addr.c_str()); memset(server_addr.sin_zero, '\0', sizeof(server_addr.sin_zero)); /* Bind */ bind(sockListen, (struct sockaddr *)&server_addr, sizeof(server_addr)); makeTopologyFromFile(DEFAULT_TOPOLOGY_FILE) ; // Initialisation de "area_list". makeWaypointListFromFile(DEFAULT_WAYPOINT_FILE) ; // Initialisation de "waypoint_list" et "waypoint_matrix". makeReferencePointListFromFile(ref_pt_file.c_str()) ; // Initialisation de "reference_point_list". /* *** À commenter pour utiliser les mesures centrées mobile de Fred */ if (! checkTopology()) // Vérifications. { cerr << "Topology flawed. Exiting program." << endl ; exit(1) ; // Si problème, on quitte. } /* Fin du bloc à commenter *** */ makeReferencePointDistances() ; // Initialisation de "reference_point_matrix". makeApListFromFile(ap_file.c_str()) ; // Initialisation de "access_point_list". #ifdef DEBUG_T cout << "//<-- Server::Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T } Server::~Server() { #ifdef DEBUG_T cout << "//--> Server::~Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T close(sockListen); close(sockSend); reference_point_list.clear(); access_point_list.clear(); client_list.clear(); #ifdef DEBUG_T cout << "//<-- Server::~Server()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::send_to_client(const int &cl) { /* Do not forget to implement later: usefull for a demo */ } int Server::receive_data() { /* Do not forget to implement later: usefull for a demo */ return 0; } /* Cherche dans quelle(s) zone(s) se situe un point. * Retourne une map contenant la liste des zones auxquelles le Point "p" appartient. */ map Server::inWhichAreas(const Point &p) { #ifdef DEBUG_T cout << "//--> Server::inWhichAreas()" << endl ; fflush(stdout) ; #endif // DEBUG_T map areas ; for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) if (it->second.containsPoint(p)) areas.insert(make_pair(it->first, it->second)) ; #ifdef DEBUG_T cout << "//<-- Server::inWhichAreas()" << endl ; fflush(stdout) ; #endif // DEBUG_T return areas ; } /* Retourne true si les points "p1" et "p2" sont dans la même zone (ou ont au moins une zone en commun s'ils appartiennent à plusieurs zones). */ bool Server::inTheSameArea(const Point &p1, const Point &p2) { #ifdef DEBUG_T cout << "//--> Server::inTheSameArea()" << endl ; fflush(stdout) ; #endif // DEBUG_T map // Liste des zones comportant les points p1 et p2 : zones1(inWhichAreas(p1)), zones2(inWhichAreas(p2)) ; #ifdef DEBUG_2 cout << " zones1 (" << zones1.size() << ") : [" ; for (map::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) cout << it1->first << ',' ; cout << "\b]" ; cout << " zones2 (" << zones2.size() << ") : [" ; for (map::iterator it1 = zones2.begin() ; it1 != zones2.end() ; it1++) cout << it1->first << ',' ; cout << "\b]" ; #endif // DEBUG_2 if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, { #ifdef DEBUG_T cout << "//<-- Server::inTheSameArea()" << endl ; fflush(stdout) ; #endif // DEBUG_T return false ; // on quitte. } for (map::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) // Parcours des zones : for (map::iterator it2 = zones2.begin() ; it2 != zones2.end() ; it2++) if (it1->second == it2->second) // Si les deux zones sont identiques, { #ifdef DEBUG_T cout << "//<-- Server::inTheSameArea()" << endl ; fflush(stdout) ; #endif // DEBUG_T return true ; // p1 et p2 sont dans la même zone. } #ifdef DEBUG_T cout << "//<-- Server::inTheSameArea()" << endl ; fflush(stdout) ; #endif // DEBUG_T return false ; } /* Cherche les points de passage communs aux zones "z1" et "z2". * Retourne un vector contenant la liste de ces points. */ vector Server::areaConnection(const Area &z1, const Area &z2) { #ifdef DEBUG_T cout << "//--> Server::areaConnection(Area&, Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T vector points ; for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) { map areas(inWhichAreas(waypoint_list[i])) ; if (areas.find(z1.getName()) != areas.end() && areas.find(z2.getName()) != areas.end()) points.push_back(waypoint_list[i]) ; } #ifdef DEBUG_T cout << "//<-- Server::areaConnection(Area&, Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points ; } /* Cherche les points de passage de la zone "z". * Retourne un vector contenant la liste de ces points. */ vector Server::areaConnection(const Area &z) { #ifdef DEBUG_T cout << "//--> Server::areaConnection(Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T vector points ; for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) { map areas(inWhichAreas(waypoint_list[i])) ; if (areas.find(z.getName()) != areas.end()) points.push_back(waypoint_list[i]) ; } #ifdef DEBUG_T cout << "//<-- Server::areaConnection(Area&)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points ; } /* Calcule la distance entre les points "p1" et "p2" en tenant compte de la topologie. */ float Server::distanceTopology(const Point &p1, const Point &p2) { #ifdef DEBUG_T cout << "//--> Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T map zones1(inWhichAreas(p1)), zones2(inWhichAreas(p2)) ; if (zones1.size() == 0 || zones2.size() == 0) // Si aucune zone ne contient p1 ou p2, { #ifdef DEBUG_2 cout << "Aucune zone ne contient " << p1 << " (" << zones1.size() << " zones) ou " << p2 << " (" << zones2.size() << " zones)." << endl ; #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte. } Area z1(zones1.begin()->second), // Première zone d'appartenance du point p1. // FIXME : vérifier toutes les zones z2(zones2.begin()->second) ; vector connection ; /* *** Cas de la même zone *** */ if (z1 == z2) // Si les points sont dans la même zone, { #ifdef DEBUG_2 cout << p1 << " et " << p2 << " sont dans la même zone." << endl ; #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return p1.distance(p2) ; // la distance entre eux est la distance euclidienne. } /* *** Cas de deux zones voisines (connectées directement) *** */ if ((connection = areaConnection(z1, z2)).size() != 0) // Si les points sont dans deux zones voisines, { // la distance entre eux est la distance euclidienne de chacun jusqu'au plus proche point de passage entre les deux zones. #ifdef DEBUG_2 cout << p1 << " et " << p2 << " sont dans deux zones voisines." << endl ; #endif // DEBUG_2 float dist = p1.distance(connection[0]) + p2.distance(connection[0]) ; for (unsigned int i = 1 ; i < connection.size() ; i++) // Recherche du point de passage offrant la plus courte distance { float tmp_dist = p1.distance(connection[i]) + p2.distance(connection[i]) ; if (tmp_dist < dist) dist = tmp_dist ; } #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return dist ; } /* *** Les points sont dans des zones non-voisines *** */ #ifdef DEBUG_2 cout << p1 << " et " << p2 << " sont dans des zones non-voisines." << endl ; #endif // DEBUG_2 vector // Liste des points de passage appartenant respectivement à z1 et à z2. wp_z1(areaConnection(z1)), wp_z2(areaConnection(z2)) ; int // Indices des points de passage dans la liste : wp_z1_idx, wp_z2_idx = -1 ; // z2 ne peut pas être utilisé non initialisé, contrairement à ce que dit GCC, car dans le cas où il n'est pas initialisé on quitte la fonction avant de l'utiliser (cf. "return -1" un peu plus bas); if (wp_z1.size() == 0 || wp_z2.size() == 0) // Si l'une des deux zones ne comporte aucun point de passage, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte (ceci ne devrait jamais se produire). } /* Première itération (voir explication de l'algorithme plus bas) */ unsigned int i1, i2 ; for (i1 = 0 ; i1 < wp_z1.size() ; i1++) // Recherche des premiers indices valides (où il existe un chemin entre les points de passage) { wp_z1_idx = pointIndex(waypoint_list, wp_z1[i1]) ; for (i2 = 0 ; i2 < wp_z2.size() ; i2++) { wp_z2_idx = pointIndex(waypoint_list, wp_z2[i2]) ; if (wp_z2_idx < 0) continue ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, break ; // on arrête le parcours. } if (waypoint_matrix[wp_z1_idx][wp_z2_idx] != -1) // Si c'est bon, break ; // on arrête le parcours. } if (i1 >= wp_z1.size()) // Si on a parcouru tout le tableau sans trouver de chemin, { #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // on quitte. } float dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[i2]), tmp_dist ; for (unsigned int j = i2 + 1 ; j < wp_z2.size() ; j++) // Fin du parcours : { wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) continue ; tmp_dist = p1.distance(wp_z1[i1]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; if (tmp_dist < dist) dist = tmp_dist ; } /* Itérations suivantes */ for (unsigned int i = i1 + 1 ; i < wp_z1.size() ; i++) for (unsigned int j = 0 ; j < wp_z2.size() ; j++) { // Indice des points de passage wp_z1[i] et wp_z2[j] dans la liste des points de passage : wp_z1_idx = pointIndex(waypoint_list, wp_z1[i]) ; wp_z2_idx = pointIndex(waypoint_list, wp_z2[j]) ; if (waypoint_matrix[wp_z1_idx][wp_z2_idx] == -1) // S'il n'existe aucun chemin entre les deux points de passage continue ; /* La distance entre p1 et p2 est égale à la somme de : * - la distance entre p1 et le point de passage courant de z1 * (distance cartésienne car ils appartiennent à la même zone), * - la distance entre p2 et le point de passage courant de z2 (idem), * - la distance entre les deux points de passages suscités, qui est * donnée par la matrice des distances entre points de passage * (waypoint_matrix). * On conservera bien sûr la somme qui donne le chemin le plus court. */ tmp_dist = p1.distance(wp_z1[i]) + waypoint_matrix[wp_z1_idx][wp_z2_idx] + p2.distance(wp_z2[j]) ; if (tmp_dist < dist) dist = tmp_dist ; } #ifdef DEBUG_T cout << "//<-- Server::distanceTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return dist ; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Recherche un point de coordonnées (x;y;z) dans la liste reference_point_list, retourne true s'il existe, false sinon. */ inline bool Server::pointExists(const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(reference_point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Recherche un Point dans la liste reference_point_list, retourne true s'il existe, false sinon. */ inline bool Server::pointExists(const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(reference_point_list, p) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Recherche un point de coordonnées (x;y;z) dans la liste "point_list", retourne true s'il existe, false sinon. */ inline bool Server::pointExists(const vector &point_list, const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = pointExists(point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Recherche un Point dans la liste "point_list", retourne true s'il existe, false sinon. */ inline bool Server::pointExists(const vector &point_list, const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointExists(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = (pointIndex(point_list, p) != -1) ; #ifdef DEBUG_T cout << "//<-- Server::pointExists(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } inline int Server::pointIndex(const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(reference_point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } inline int Server::pointIndex(const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(reference_point_list, p) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } inline int Server::pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int ret = pointIndex(point_list, Point(x, y, z)) ; #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &float, &float, &float)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } inline int Server::pointIndex(const vector &point_list, const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; for (i = 0 ; i < point_list.size() ; i++) if (p == point_list[i].getCoordinates()) { #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return i ; } #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; // Point non trouvé } /* Retourne la position du Point "p" dans le tableau à une dimension "point_tab" de taille "size", ou -1 en cas d'échec. */ inline int Server::pointIndex(const Point *point_tab, unsigned int &size, const Point &p) const { for (unsigned int i = 0 ; i < size ; i++) if (point_tab[i] == p) return i ; return -1 ; } /* Retourne la position du Point "p" dans le vector "point_list", ou -1 en cas d'échec. */ inline int Server::pointIndex(const vector &point_list, const Point &p) const { #ifdef DEBUG_T cout << "//--> Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T for (unsigned int i = 0 ; i < point_list.size() ; i++) if (point_list[i] == p) { #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return i ; } #ifdef DEBUG_T cout << "//<-- Server::pointIndex(&vector, &Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return -1 ; } bool Server::apExists(const string &ap_addr)const { #ifdef DEBUG_T cout << "//--> Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T string str; for (unsigned int i = 0 ; i < access_point_list.size() ; i++) { str = access_point_list[i].getApAddr() ; const int length = str.length() ; for (int j = 0 ; j < length ; ++j) str[j] = std::tolower(str[j]) ; if (str == ap_addr) { #ifdef DEBUG_T cout << "//<-- Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T return true ; } } #ifdef DEBUG_T cout << "//<-- Server::apExists()" << endl ; fflush(stdout) ; #endif // DEBUG_T return false ; } unsigned int Server::apIndex(const string &ap_addr)const { #ifdef DEBUG_T cout << "//--> Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; string str; for (i = 0 ; i < access_point_list.size() ; i++) { str = access_point_list[i].getApAddr() ; const int length = str.length() ; for (int j = 0 ; j < length ; ++j) str[j] = std::tolower(str[j]) ; if (str == ap_addr) { #ifdef DEBUG_T cout << "//<-- Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T return i; } } #ifdef DEBUG_T cout << "//<-- Server::apIndex()" << endl ; fflush(stdout) ; #endif // DEBUG_T return 0; // Should never happen } /* Selects the "k" closest points from the measurement "m", in the SS space. * Returns an empty vector if no points are found, which should never happen. */ vector Server::getkClosestInSs(const vector &m, const unsigned int &k)const { #ifdef DEBUG_T cout << "//--> Server::getkClosestInSs(&vector, &unsigned int)" << endl ; cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T return getkClosestInSs(m, k, NULL) ; } /* Selects the "k" closest points from the measurement "m", in the SS space. * If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. * Returns an empty vector if no points are found, which should never happen. */ vector Server::getkClosestInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const { #ifdef DEBUG_T cout << "//--> Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i, j, min_idx; vector distances_vector; vector points_vector; Point tmp_pt; float tmp_distance = 0, dist_max = 10000000, tmp_min; for (i = 0 ; i < reference_point_list.size() ; i++) if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) { tmp_distance = reference_point_list[i].getSsSquareDistance(m); #ifdef DEBUG_2 cout << tmp_distance << " " ; #endif // DEBUG_2 /* if not k points, add it */ if(distances_vector.size() < k) { distances_vector.push_back(tmp_distance); points_vector.push_back(reference_point_list[i].getCoordinates()); dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; } else { /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ if(dist_max > tmp_distance) { /* remove old max */ for (j = 0 ; j < distances_vector.size() ; j++) if (distances_vector[j] == dist_max) { distances_vector[j] = tmp_distance; points_vector[j] = reference_point_list[i].getCoordinates(); break; } /* Now seek the new max. distance */ dist_max = distances_vector[0]; for(j = 1 ; j < distances_vector.size() ; j++) if(distances_vector[j] > dist_max) dist_max = distances_vector[j]; } /* Else nothing needs to be done */ } } #ifdef DEBUG_2 cout << endl ; #endif // DEBUG_2 /* Sorts the vector */ for (i = 0 ; i < distances_vector.size() - 1 ; i++) { tmp_min = distances_vector[i]; min_idx = i; for (j = i+1 ; j < distances_vector.size() ; j++) if (tmp_min > distances_vector[j]) { tmp_min = distances_vector[j]; min_idx = j; } if (min_idx != i) { /* Swap points */ tmp_pt = points_vector[i]; points_vector[i] = points_vector[min_idx]; points_vector[min_idx] = tmp_pt; /* Swap distances */ distances_vector[min_idx] = distances_vector[i]; distances_vector[i] = tmp_min; } } #ifdef DEBUG cout << "getkClosestInSs() : Points sélectionnés :" << endl ; if (distances_vector.size() != points_vector.size()) cout << "Erreur ! distances_vector.size()=" << distances_vector.size() << " != points_vector.size()=" << points_vector.size() << endl ; else for (i = 0 ; i < distances_vector.size() ; i++) cout << distances_vector[i] << " : " << points_vector[i] << endl ; #endif // DEBUG #ifdef DEBUG_T cout << "//<-- Server::getkClosestInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return points_vector; } Point Server::getkWeightedInSs(const vector &m, const unsigned int &k)const { #ifdef DEBUG_T cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret = getkWeightedInSs(m, k, NULL) ; #ifdef DEBUG_T cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* If "point_ignored" is not NULL, the Point "*point_ignored" is ignored. */ Point Server::getkWeightedInSs(const vector &m, const unsigned int &k, const Point *point_ignored)const { #ifdef DEBUG_T cout << "//--> Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i, j; vector distances_vector; vector points_vector; float tmp_distance = 0, dist_max = 10000000; Point ret; float total = 0, x = 0, y = 0, z = 0; for (i = 0 ; i < reference_point_list.size() ; i++) if (point_ignored == NULL || (reference_point_list[i].getCoordinates() != *point_ignored)) { tmp_distance = reference_point_list[i].getSsSquareDistance(m); /* if not k points, add it */ if (distances_vector.size() < k) { distances_vector.push_back(tmp_distance); points_vector.push_back(reference_point_list[i].getCoordinates()); dist_max = (dist_max < tmp_distance) ? tmp_distance : dist_max; } else { /* if tmp_dst < dist_max, should add it and remove previous greatest dist. */ if (dist_max > tmp_distance) { /* remove old max */ for (j = 0 ; j < distances_vector.size() ; j++) if(distances_vector[j] == dist_max) { dist_max = tmp_distance; distances_vector.erase(distances_vector.begin() + j); points_vector.erase(points_vector.begin() + j); distances_vector.push_back(tmp_distance); points_vector.push_back(reference_point_list[i].getCoordinates()); break; } } /* Else nothing needs to be done */ } } for (i = 0 ; i < distances_vector.size() ; i++) total += (1 / distances_vector[i]); for (i = 0 ; i < distances_vector.size() ; i++) { x += points_vector[i].getX() * (1 / distances_vector[i]) / total; y += points_vector[i].getY() * (1 / distances_vector[i]) / total; z += points_vector[i].getZ() * (1 / distances_vector[i]) / total; } ret.setX(x); ret.setY(y); ret.setZ(z); #ifdef DEBUG_T cout << "//<-- Server::getkWeightedInSs(&vector, &unsigned int, *Point)" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret; } Point Server::kPointsAverage(const vector &vp)const { #ifdef DEBUG_T cout << "//--> Server::kPointsAverage()" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int i; float x=0, y=0, z=0; Point p; for (i = 0 ; i < vp.size() ; i++) { x += vp[i].getX(); y += vp[i].getY(); z += vp[i].getZ(); } p.setX(x / (float) vp.size()); p.setY(y / (float) vp.size()); p.setZ(z / (float) vp.size()); #ifdef DEBUG_T cout << "//<-- Server::kPointsAverage()" << endl ; fflush(stdout) ; #endif // DEBUG_T return p; } Point Server::fbcm(const vector &m, const int &client_idx)const { #ifdef DEBUG_T cout << "//--> Server::fbcm()" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret(0, 0, 0); vector addr; vector dist_vect; vector centres; unsigned int i, ap_idx; float constant_term, minmax_res, minmax_max; float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; i = 0; //cout << "FBCM: "; for (i = 0 ; i < m.size() ; i++) if (apExists(m[i].getMacAddr())) { ap_idx = apIndex(m[i].getMacAddr()); //cout << "AP idx: " << ap_idx << " "; centres.push_back(access_point_list[ap_idx].getCoordinates()); addr.push_back(m[i].getMacAddr()); constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. //cout << "20log(" << (300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI) << ") = "; //cout << constant_term << " "; dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / (10 * access_point_list[ap_idx].getFriisIndex()))); //cout << endl; } /* Then: min-max */ minmax_res = 1000000; for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) for(z = MINMAX_Z_START ; z <= MINMAX_Z_STOP ; z += MINMAX_STEP) { minmax_max = 0; for (i = 0 ; i < centres.size() ; i++) if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; if (minmax_max < minmax_res) { ret.setX(x); ret.setY(y); ret.setZ(z); minmax_res = minmax_max; } } /* Clear all vectors */ addr.clear(); dist_vect.clear(); centres.clear(); #ifdef DEBUG_T cout << "//<-- Server::fbcm()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Return position */ return ret; } /*second version of fbcm with as parameter vector &m and a list of friis index*/ Point Server::fbcm_friis( const vector &m, const vector friis_idx_list, const float &z)const { #ifdef DEBUG_T cout << "//--> Server::fbcm_friis()" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret(0, 0, 0); //vector addr; vector dist_vect; vector centres; unsigned int i, j, ap_idx; float constant_term, minmax_res, minmax_max; float x = MINMAX_X_START, y = MINMAX_Y_START ; vector vm = m; //Used when filtering 3 strongest APs vector friis_idx = friis_idx_list; //Used when filtering 3 strongest APs i = 0; //cout << "FBCM: "; cout << "Received " << vm.size() << " measurements." << endl; for (i = 0 ; i < vm.size() ; i++) { if (apExists(vm[i].getMacAddr())) { ap_idx = apIndex(vm[i].getMacAddr()); cout << "AP " << vm[i].getMacAddr() << " was found at position " << ap_idx << endl; constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain() + 2; constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)); if(friis_idx[i] != -1) { centres.push_back(access_point_list[ap_idx].getCoordinates()); dist_vect.push_back(pow(10, (constant_term - vm[i].getAverage()) / (10 * friis_idx[i]))); } } } cout << "Computed " << dist_vect.size() << " Friis indexes. Values:" << endl; for (j = 0 ; j < dist_vect.size() ; j++) cout << "dist_vect du point d'accés: " << centres[j] << "--->>>" << dist_vect[j] < minmax_max) minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; if (minmax_max < minmax_res) { ret.setX(x); ret.setY(y); ret.setZ(z); minmax_res = minmax_max; } } /* Clear all vectors */ // addr.clear(); dist_vect.clear(); centres.clear(); //cout << "RESULTAT DU FRBHM ---> " << ret << endl ; #ifdef DEBUG_T cout << "//<-- Server::fbcm_friis()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Return position */ return ret; } Point Server::interlink(const vector &m, const int &client_idx)const { #ifdef DEBUG_T cout << "//--> Server::interlink()" << endl ; fflush(stdout) ; #endif // DEBUG_T Point ret(0, 0, 0); vector addr; vector dist_vect; vector centres; unsigned int i, ap_idx; float constant_term, minmax_res, minmax_max; float x = MINMAX_X_START, y = MINMAX_Y_START, z = MINMAX_Z_START; i = 0; for (i = 0 ; i < m.size() ; i++) if (apExists(m[i].getMacAddr())) { ap_idx = apIndex(m[i].getMacAddr()); centres.push_back(access_point_list[ap_idx].getCoordinates()); addr.push_back(m[i].getMacAddr()); constant_term = access_point_list[ap_idx].getOutputPower() + access_point_list[ap_idx].getAntennaGain(); constant_term += 20 * log10((300000000.0 / (float) access_point_list[ap_idx].getFrequency()) / (4*M_PI)) + 2; //end of expr. should be: client_list[client_idx].getAntennaGain() instead of 2. dist_vect.push_back(pow(10, (constant_term - m[i].getAverage()) / 35)); } /* Then: min-max */ minmax_res = 1000000; for (x = MINMAX_X_START ; x < MINMAX_X_STOP ; x += MINMAX_STEP) for (y = MINMAX_Y_START ; y < MINMAX_Y_STOP ; y += MINMAX_STEP) for(z = MINMAX_Z_START ; z < MINMAX_Z_STOP ; z += MINMAX_STEP) { minmax_max = 0; for (i = 0 ; i < centres.size() ; i++) if (abs(centres[i].distance(x, y, z) - dist_vect[i]) > minmax_max) minmax_max = abs(centres[i].distance(x, y, z) - dist_vect[i]) ; if (minmax_max < minmax_res) { ret.setX(x); ret.setY(y); ret.setZ(z); minmax_res = minmax_max; } } /* Clear all vectors */ addr.clear(); dist_vect.clear(); centres.clear(); #ifdef DEBUG_T cout << "//<-- Server::interlink()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* Return position */ return ret; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Crée la liste des points de référence dans la liste reference_point_list. */ void Server::makeReferencePointListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&string)" << endl ; fflush(stdout) ; #endif // DEBUG_T makePointListFromFile(reference_point_list, filename, true) ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&string)" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::makePointListFromFile(vector &dest_point_list, const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&vector, &string)" << endl ; fflush(stdout) ; #endif // DEBUG_T makePointListFromFile(dest_point_list, filename, true) ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&vector, &string)" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit le fichier de mesures (CSV) nommé "filename", et place les informations dans la liste "dest_point_list". * Si "uniq_point" est vrai, on vérifiera l'existence d'un point avant tout ajout d'information, de manière à ne pas créer de doublon : si le point existe déjà, les informations lui seront ajoutées, sinon un nouveau point sera créé dans la liste. * Si "uniq_point" est faux, un nouveau point sera créé pour chaque ligne du fichier. */ void Server::makePointListFromFile(vector &dest_point_list, const string &filename, const bool uniq_point) { #ifdef DEBUG_T cout << "//--> Server::makePointListFromFile(&vector, &string, bool)" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file ; // Flux d'entrée du fichier. char buffer[BUFFER_LENGTH]; // Buffer lu dans le fichier. string cpp_buffer ; // Buffer au format string. ReferencePoint rp; Point tmp_point; float x, y, z ; // Coordonnées des points. unsigned int pt_idx = 0 ; // Position du point lu dans la liste. vector infos ; // Liste des informations lues dans une ligne du fichier. input_file.open(filename.c_str()) ; if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." ; int nlines = 0 ; int npoints = 0 ; #endif // DEBUG while (!input_file.eof()) { #ifdef DEBUG if (nlines % 100 == 0) printf("\n%5d", nlines) ; cout << '.' ; nlines++ ; #endif // DEBUG input_file.getline(buffer, BUFFER_LENGTH); if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Extract fields */ cpp_buffer = buffer; if (cpp_buffer.size() == 0) // Ignorer une ligne vide continue ; infos = extractReferencePointInfoFromBuffer(cpp_buffer); x = string2float(infos[0]); y = string2float(infos[1]); #ifdef FRED_CSV_FORMAT z = DEFAULT_Z ; #else // FRED_CSV_FORMAT z = string2float(infos[2]) ; #endif // FRED_CSV_FORMAT /* Set point coordinates */ tmp_point.setX(x); tmp_point.setY(y); tmp_point.setZ(z); /* Use C++ string format */ if (!uniq_point || !pointExists(dest_point_list, tmp_point)) // Si on ne veut pas de points unique, ou que le point n'existe pas encore, { rp.setCoordinates(tmp_point); dest_point_list.push_back(rp) ; // on le crée. pt_idx = dest_point_list.size() - 1 ; // Le point que l'on vient d'ajouter est le dernier du vector. #ifdef DEBUG npoints++ ; #endif // DEBUG #ifdef DEBUG_2 cout << tmp_point << " : ajouté." << endl ; #endif // DEBUG_2 } else // Le point existe déjà : { #ifdef DEBUG_2 cout << tmp_point << " : existe déjà." << endl ; #endif // DEBUG_2 pt_idx = pointIndex(dest_point_list, tmp_point) ; // On recherche le point auquel on veut ajouter les informations. } #ifdef FRED_CSV_FORMAT vector measures_vector = extractValues(infos[4]) ; for (unsigned int i = 0 ; i < measures_vector.size() ; i++) dest_point_list[pt_idx].addMeasurement(infos[3], measures_vector[i]); measures_vector.clear(); #else // FRED_CSV_FORMAT for (unsigned int i = 4 ; i < infos.size() ; i++) { #ifdef DEBUG_2 cout << "Lecture de la valeur : " << infos[i] << "... " ; #endif // DEBUG_2 if (i + 1 < infos.size()) { dest_point_list[pt_idx].addMeasurement(infos[i], string2int(infos[i+1])) ; #ifdef DEBUG_2 cout << "Mesure ajoutée : AP = " << infos[i] << " | SS = " << string2int(infos[i+1]) << endl ; #endif // DEBUG_2 i++ ; } } #endif // FRED_CSV_FORMAT } } #ifdef DEBUG cout << '\n' << nlines << " lignes lues, " << npoints << " points différents ajoutés.\n" << endl ; #endif // DEBUG input_file.close(); infos.clear() ; #ifdef DEBUG_T cout << "//<-- Server::makePointListFromFile(&vector, &string, bool)" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::makeApListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeApListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file; char buffer[BUFFER_LENGTH]; vector ap_infos; AccessPoint tmp_ap; input_file.open(filename.c_str()); if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH); if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. ap_infos = explode(buffer, ';'); #ifdef DEBUG cout << "AP : " << buffer ; #endif // DEBUG tmp_ap.setApAddr(ap_infos[0]); tmp_ap.setCoordinates(string2float(ap_infos[1]), string2float(ap_infos[2]), string2float(ap_infos[3])); tmp_ap.setFrequency(string2uint(ap_infos[4])); tmp_ap.setAntennaGain(string2float(ap_infos[5])); tmp_ap.setOutputPower(string2float(ap_infos[6])); access_point_list.push_back(tmp_ap); ap_infos.clear(); #ifdef DEBUG cout << " ajouté." << endl ; #endif // DEBUG } } #ifdef DEBUG cout << endl ; #endif // DEBUG input_file.close(); #ifdef DEBUG_T cout << "//<-- Server::makeApListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit la liste des zones homogènes du bâtiment (pièces) dans le fichier "filename", et place le résultat dans "area_list". */ void Server::makeTopologyFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeTopologyFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T ifstream input_file ; char buffer[BUFFER_LENGTH] ; vector infos ; input_file.open(filename.c_str()) ; if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH) ; if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. infos = explode(buffer, ';') ; #ifdef DEBUG cout << "Pièce : " << buffer ; #endif // DEBUG if (area_list.find(infos[0]) != area_list.end()) // Si la pièce existe déjà, cerr << "Erreur ! Déclaration multiple de la zone « " << infos[0] << " »." << endl ; // on le signale ; else // sinon on l'ajoute : { area_list[infos[0]] = Area(infos[0], string2float(infos[1]), string2float(infos[3]), string2float(infos[2]), string2float(infos[4]), string2float(infos[5]), string2float(infos[6])) ; #ifdef DEBUG cout << " ajoutée." << endl ; #endif // DEBUG } infos.clear() ; } } #ifdef DEBUG cout << "--> Liste des pièces (" << area_list.size() << ") :" << endl ; for (map::iterator it = area_list.begin() ; it != area_list.end() ; it++) cout << it->first << " : " << it->second << endl ; cout << endl ; #endif // DEBUG input_file.close() ; #ifdef DEBUG_T cout << "//<-- Server::makeTopologyFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Lit la liste des points de passage dans le fichier "filename" et calcule les distances entre eux. Initialise waypoint_list et waypoint_matrix. * TODO : tenir compte de la topologie pour les distances entre points. */ void Server::makeWaypointListFromFile(const string &filename) { #ifdef DEBUG_T cout << "//--> Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T /* *** Lecture du fichier *** */ ifstream input_file ; char buffer[BUFFER_LENGTH] ; vector infos ; set point_list ; input_file.open(filename.c_str()); if (input_file.fail()) { cerr << "Error opening input file « " << filename << " » !" << endl ; #ifdef DEBUG_T cout << "//<-- Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T return ; } #ifdef DEBUG cout << "Lecture du fichier « " << filename << " »..." << endl ; #endif // DEBUG while (!input_file.eof()) { input_file.getline(buffer, BUFFER_LENGTH) ; if ((input_file.rdstate() & ifstream::eofbit) == 0) { /* Traitement basique des commentaires */ if (buffer[0] == '\0' // Ligne vide || buffer[0] == '#') // ou ligne commençant par # continue ; // ignorer cette ligne. infos = explode(buffer, ';') ; #ifdef DEBUG cout << "Point de passage : " << buffer << ' ' ; fflush(stdout); #endif // DEBUG /* Ajout du point lu */ Point tmp_pt(string2float(infos[0]), string2float(infos[1]), string2float(infos[2])) ; if (! point_list.insert(tmp_pt).second) cerr << "Point " << tmp_pt << " non ajouté ! Peut-être est-il dupliqué ?" << endl ; #ifdef DEBUG else cout << "traité." << endl ; fflush(stdout); #endif // DEBUG infos.clear() ; } } input_file.close() ; // Lecture du fichier terminée /* *** Construction de la matrice des distances *** */ unsigned int nb_pts = point_list.size() ; // Nombre de points unsigned int cur_idx = 0 ; // Itérateur sur l'indice de la matrice. waypoint_list.reserve(nb_pts) ; // Vector contenant tous les points (attribut du serveur) waypoint_matrix = new float*[nb_pts] ; // Matrice (carrée) des distances entre les points de passage (attribut du serveur) for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : { waypoint_matrix[i] = new float[nb_pts] ; for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 waypoint_matrix[i][k] = -1 ; } #ifdef DEBUG cout << "Traitement des points de passage (" << nb_pts << ")..." ; #endif // DEBUG #ifdef DEBUG_2 cout << "--> Liste des points de passage (" << nb_pts << ") :" << endl ; fflush(stdout); #endif // DEBUG_2 /* Initialisation (voisinage de premier ordre de chaque point */ for (set::iterator it = point_list.begin() ; it != point_list.end() ; it++, cur_idx++) // Pour chaque point enregistré { #ifdef DEBUG if (cur_idx % 100 == 0) printf("\n%5d", cur_idx) ; cout << '.' ; fflush(stdout) ; #endif // DEBUG #ifdef DEBUG_2 cout << *it << " :" ; #endif // DEBUG_2 waypoint_list.push_back(*it) ; // Ajout du point dans waypoint_list waypoint_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent { #ifdef DEBUG_2 cout << " / " << waypoint_list[k] ; #endif // DEBUG_2 if (inTheSameArea(waypoint_list[cur_idx], waypoint_list[k])) // Si le point est dans la même zone, { float dist = it->distance(waypoint_list[k]) ; // on calcule la distance waypoint_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, waypoint_matrix[k][cur_idx] = dist ; // dans les deux sens. } } #ifdef DEBUG_2 cout << " /" << endl ; #endif // DEBUG_2 } #ifdef DEBUG cout << endl ; #endif // DEBUG #ifdef DEBUG_2 /* Premier affichage de la matrice */ cout << "--> Matrice des distances entre points de passage (après initialisation) :\n\t\t|" ; for (unsigned int k = 0 ; k < nb_pts ; k++) cout << ' ' << waypoint_list[k] << "\t|" ; cout << endl ; for (unsigned int k = 0 ; k < nb_pts ; k++) { cout << waypoint_list[k] << "\t|" ; for (unsigned int l = 0 ; l < nb_pts ; l++) cout << '\t' << waypoint_matrix[k][l] << "\t|" ; cout << endl ; } cout << endl ; #endif // DEBUG_2 /* Itérations suivantes */ bool comput_done = true ; while (comput_done) { comput_done = false ; for (unsigned int i = 0 ; i < nb_pts ; i++) for (unsigned int j = 0 ; j < nb_pts ; j++) if (waypoint_matrix[i][j] > 0) for (unsigned int k = 0 ; k < nb_pts ; k++) if (waypoint_matrix[j][k] > 0) { /* /!\ * NE PAS OPTIMISER (g++ -O0) ! * Avec l'option d'optimisation de GCC (-O1, -O2 ou -O3), le test : * (tmp_dist < round_float_2(waypoint_matrix[i][k]) || waypoint_matrix[i][k] == -1) * est vrai, même si les deux comparaisons sont fausses. * Cela semble provenir de la variable tmp_dist. */ float tmp_dist = round_float_2(waypoint_matrix[j][k] + waypoint_matrix[i][j]) ; if (tmp_dist < round_float_2(waypoint_matrix[i][k]) || waypoint_matrix[i][k] == -1) { waypoint_matrix[i][k] = tmp_dist ; comput_done = true ; } } } #ifdef DEBUG_2 /* Deuxième affichage de la matrice */ cout << "--> Matrice des distances entre points de passage :\n\t\t|" ; for (unsigned int k = 0 ; k < nb_pts ; k++) cout << ' ' << waypoint_list[k] << "\t|" ; cout << endl ; for (unsigned int k = 0 ; k < nb_pts ; k++) { cout << waypoint_list[k] << "\t|" ; for (unsigned int l = 0 ; l < nb_pts ; l++) cout << '\t' << waypoint_matrix[k][l] << "\t|" ; cout << endl ; } cout << endl ; #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::makeWaypointListFromFile()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Vérifie la cohérence de la topologie décrite dans les fichiers de configuration. * Retourne false si un problème est détecté, true sinon. * /!\ La liste des *points de passage*, leur *matrice de distances*, ainsi que la liste des *points de référence*, DOIVENT ÊTRE INITIALISÉES avant l'appel à cette fonction. Il faut donc appeler makeWaypointListFromFile() et makeReferencePointListFromFile() avant checkTopology(). */ bool Server::checkTopology() { #ifdef DEBUG_T cout << "//--> Server::checkTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T bool ret = true ; /* *** Recherche de points de passage n'appartenant à aucune zone *** */ for (unsigned int i = 0 ; i < waypoint_list.size() ; i++) { map areas(inWhichAreas(waypoint_list[i])) ; if (areas.empty()) { #ifdef DEBUG cout << "Le point de passage " << waypoint_list[i] << " n'appartient à aucune zone !" << endl ; #endif // DEBUG ret = false ; } #ifdef DEBUG_2 else { cout << "Le point de passage " << waypoint_list[i] << " appartient aux zones suivantes :" << endl ; for (map::iterator it = areas.begin() ; it != areas.end() ; it++) cout << '\t' << it->first << endl ; } #endif // DEBUG_2 } /* *** Recherche de points de référence n'appartenant à aucune zone *** */ for (unsigned int i = 0 ; i < reference_point_list.size() ; i++) { map areas(inWhichAreas((Point) reference_point_list[i])) ; if (areas.empty()) { #ifdef DEBUG cout << "Le point de référence " << (Point) reference_point_list[i] << " n'appartient à aucune zone !" << endl ; #endif // DEBUG ret = false ; // À modifier si on veut permettre aux points de référence de n'appartenir à aucune zone. } #ifdef DEBUG_2 else { cout << "Le point de référence " << (Point) reference_point_list[i] << " appartient aux zones suivantes :" << endl ; for (map::iterator it = areas.begin() ; it != areas.end() ; it++) cout << '\t' << it->first << endl ; } #endif // DEBUG_2 } /* *** Recherche des pièces non connectées (et liste des connexions entre pièces) *** */ set connected_areas ; // Liste des zones connectées à au moins une autre zone (on n'enregistre que le nom des zones, dupliquer toutes les zones étant inutile). for (map::iterator it1 = area_list.begin() ; it1 != area_list.end() ; it1++) for (map::iterator it2 = area_list.begin() ; it2 != area_list.end() ; it2++) { if (it1 == it2) continue ; vector connect(areaConnection(it1->second, it2->second)) ; if (!connect.empty()) { connected_areas.insert(it1->first) ; // Ajout de la zone à la liste des zones connectées. #ifdef DEBUG cout << "Les zones « " << it1->first << " » et « " << it2->first << " » sont connectées par les points suivants :" << endl ; for (unsigned int i = 0 ; i < connect.size() ; i++) cout << '\t' << connect[i] << endl ; #endif // DEBUG } #ifdef DEBUG_2 else cout << "Les zones « " << it1->first << " » et « " << it2->first << " » ne sont pas connectées." << endl ; #endif // DEBUG_2 } if (connected_areas.size() != area_list.size()) { #ifdef DEBUG map orphan_areas(area_list) ; // Liste des zones orphelines (non-connectées). Copie de la liste des zones (on devrait utiliser un set ne contenant que les noms, comme pour "connected_areas", mais c'est plus compliqué à coder alors on ne va pas s'embêter, surtout pour un affichage de débogage). for (set::iterator it = connected_areas.begin() ; it != connected_areas.end() ; it++) orphan_areas.erase(*it) ; // On supprime chaque zone connectée de la liste des zones orphelines. cout << "Les zones suivantes ne sont connectées à aucune autre :" << endl ; for (map::iterator it = orphan_areas.begin() ; it != orphan_areas.end() ; it++) cout << '\t' << it->first << endl ; #endif // DEBUG ret = false ; } #ifdef DEBUG_T cout << "//<-- Server::checkTopology()" << endl ; fflush(stdout) ; #endif // DEBUG_T return ret ; } /* Calcule la distance entre tous les points de référence en tenant compte de la topologie (initialise reference_point_matrix). * /!\ La liste des *points de passage*, leur *matrice de distances*, ainsi que la liste des *points de référence*, DOIVENT ÊTRE INITIALISÉES avant l'appel à cette fonction. Il faut donc appeler makeWaypointListFromFile() et makeReferencePointListFromFile() avant makeReferencePointDistances(). */ void Server::makeReferencePointDistances() { #ifdef DEBUG_T cout << "//--> Server::makeReferencePointDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T unsigned int nb_pts = reference_point_list.size() ; // Nombre de points à traiter. /* Construction de la matrice des distances */ reference_point_matrix = new float*[nb_pts] ; // Allocation de la première dimension. for (unsigned int i = 0 ; i < nb_pts ; i++) // Initialisation de la matrice : { reference_point_matrix[i] = new float[nb_pts] ; for (unsigned int k = 0 ; k < nb_pts ; k++) // Initialisation des distances à -1 reference_point_matrix[i][k] = -1 ; } #ifdef DEBUG cout << "Traitement des points de référence (" << nb_pts << ")..." ; #endif // DEBUG #ifdef DEBUG_2 cout << "--> Liste des points de référence (" << nb_pts << ") :" << endl ; fflush(stdout); #endif // DEBUG_2 /* Calcul des distances */ for (unsigned int cur_idx = 0 ; cur_idx < nb_pts ; cur_idx++) { #ifdef DEBUG if (cur_idx % 100 == 0) printf("\n%5d", cur_idx) ; cout << '.' ; fflush(stdout) ; #endif // DEBUG #ifdef DEBUG_2 cout << (Point) reference_point_list[cur_idx] ; cout << " :" ; #endif // DEBUG_2 reference_point_matrix[cur_idx][cur_idx] = 0 ; // La distance du point à lui-même est nulle for (unsigned int k = 0 ; k < cur_idx ; k++) // Pour chacun des point précédent { #ifdef DEBUG_2 cout << " / " << (Point) reference_point_list[k] ; #endif // DEBUG_2 float dist = distanceTopology((Point) reference_point_list[cur_idx], (Point) reference_point_list[k]) ; // On calcule la distance reference_point_matrix[cur_idx][k] = dist ; // et on l'insère dans le tableau, reference_point_matrix[k][cur_idx] = dist ; // dans les deux sens. } #ifdef DEBUG_2 cout << " /" << endl ; #endif // DEBUG_2 } #ifdef DEBUG cout << endl ; #endif // DEBUG #ifdef DEBUG_2 /* Affichage de la matrice */ cout << "--> Matrice des distances entre points de référence :\n\t\t|" ; for (unsigned int k = 0 ; k < nb_pts ; k++) cout << ' ' << (Point) reference_point_list[k] << "\t|" ; cout << endl ; for (unsigned int k = 0 ; k < nb_pts ; k++) { cout << (Point) reference_point_list[k] << "\t|" ; for (unsigned int l = 0 ; l < nb_pts ; l++) cout << '\t' << reference_point_matrix[k][l] << "\t|" ; cout << endl ; } cout << endl ; #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::makeReferencePointDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Place dans "matrix" les distances entre les points de "l1" et de "l2", en les cherchant dans "reference_point_matrix". */ void Server::selectDistances(float_array *matrix, const vector &l1, const vector &l2) const { #ifdef DEBUG_T cout << "//--> Server::selectDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T matrix->resize(boost::extents[l1.size()][l2.size()]) ; for (unsigned int i = 0 ; i < l1.size() ; i++) for (unsigned int j = 0 ; j < l2.size() ; j++) (*matrix)[i][j] = reference_point_matrix[pointIndex(l1[i])][pointIndex(l2[j])] ; #ifdef DEBUG_T cout << "//<-- Server::selectDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Calcule et place dans "matrix" les distances euclidiennes entre les points de "l1" et de "l2". */ void Server::computeEuclideanDistances(float_array *matrix, const vector &l1, const vector &l2) const { #ifdef DEBUG_T cout << "//--> Server::computeEuclideanDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T matrix->resize(boost::extents[l1.size()][l2.size()]) ; for (unsigned int i = 0 ; i < l1.size() ; i++) for (unsigned int j = 0 ; j < l2.size() ; j++) (*matrix)[i][j] = l1[i].distance(l2[j]) ; #ifdef DEBUG_T cout << "//<-- Server::computeEuclideanDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Calcule et place dans "matrix" les distances euclidiennes entre les points de "l1" et de "l2". */ void Server::computeTopologyDistances(float_array *matrix, const vector &l1, const vector &l2) { #ifdef DEBUG_T cout << "//--> Server::computeTopologyDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T matrix->resize(boost::extents[l1.size()][l2.size()]) ; for (unsigned int i = 0 ; i < l1.size() ; i++) for (unsigned int j = 0 ; j < l2.size() ; j++) (*matrix)[i][j] = distanceTopology(l1[i], l2[j]) ; #ifdef DEBUG_2 cout << "computeTopologyDistances() : matrice calculée (" << l1.size() << "×" << l2.size() << ") :" << endl ; for (unsigned int i = 0 ; i < l1.size() ; i++) { for (unsigned int j = 0 ; j < l2.size() ; j++) cout << '[' << (*matrix)[i][j] << ']' ; cout << endl ; } #endif // DEBUG_2 #ifdef DEBUG_T cout << "//<-- Server::computeTopologyDistances()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* FONCTION POUR RÉTRO-COMPATIBILITÉ * Affiche la liste des points de référence (reference_point_list). */ void Server::printReferencePointList() { #ifdef DEBUG_T cout << "//--> Server::printReferencePointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T printPointList(reference_point_list) ; #ifdef DEBUG_T cout << "//<-- Server::printReferencePointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* Affiche une liste de points (point_list). */ void Server::printPointList(vector &point_list) { #ifdef DEBUG_T cout << "//--> Server::printPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T for (unsigned int i = 0 ; i < point_list.size() ; i++) cout << point_list[i] << endl ; #ifdef DEBUG_T cout << "//<-- Server::printPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::printAccessPointList() const { #ifdef DEBUG_T cout << "//--> Server::printAccessPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T for (unsigned int i = 0 ; i < access_point_list.size() ; i++) cout << access_point_list[i] << endl; #ifdef DEBUG_T cout << "//<-- Server::printAccessPointList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } void Server::computeFriisFromRefList() { #ifdef DEBUG_T cout << "//--> Server::computeFriisFromRefList()" << endl ; fflush(stdout) ; #endif // DEBUG_T vector friis_idx_list; Point pt_coords, ap_coords; float ap_power, ap_gain, calib_gain = 2, const_term, mes_power, friis_sum; unsigned int ap_freq; string ap_mac; for (unsigned int i = 0 ; i < access_point_list.size() ; i++) { ap_power = access_point_list[i].getOutputPower(); ap_coords = access_point_list[i].getCoordinates(); ap_freq = access_point_list[i].getFrequency(); ap_gain = access_point_list[i].getAntennaGain(); ap_mac = access_point_list[i].getApAddr(); /* Compute main general term, independant from scans */ const_term = calib_gain + ap_gain; const_term -= 20 * log10(4 * M_PI); const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power; /* Compute an index for each ref point. List stored in friis_idx_list */ for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) { pt_coords = reference_point_list[j].getCoordinates(); if (reference_point_list[i].getPowerForAp(ap_mac, &mes_power)) friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); } /* Now, compute avg value */ friis_sum = 0; for (unsigned int j = 0 ; j < friis_idx_list.size() ; j++) friis_sum += friis_idx_list[j]; access_point_list[i].setFriisIndex(friis_sum / friis_idx_list.size()); cout << access_point_list[i].getApAddr() << " -> " << (friis_sum / friis_idx_list.size()) << endl; friis_idx_list.clear(); } #ifdef DEBUG_T cout << "//<-- Server::computeFriisFromRefList()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /*Deuxième version de computeFriisFromRefList qui prend en entrée un point et retourne la liste d'index de friis équivalent*/ vector Server::computeFriisFromRefList(const Point &p, const vector &m) { #ifdef DEBUG_T cout << "//--> Server::computeFriisFromRefList(&Point, &vector)" << endl ; fflush(stdout) ; #endif // DEBUG_T vector friis_idx_list; Point pt_coords, ap_coords; float ap_power, ap_gain, calib_gain = 2, const_term, mes_power/*, friis_sum*/; unsigned int ap_freq; string ap_mac; for (unsigned int i = 0 ; i < access_point_list.size() ; i++) { cout << "La distance entre le point d'accès: " << access_point_list[i].getCoordinates()<< "et le point -->" << p.distance(access_point_list[i].getCoordinates()) << endl; } /* Compute an index for each ref point. List stored in friis_idx_list */ /* Compute an index for Point p. List stored in friis_idx_list */ for (unsigned int j = 0 ; j < reference_point_list.size() ; j++) { pt_coords = reference_point_list[j].getCoordinates(); if (pt_coords==p) { for (unsigned int i = 0 ; i < m.size() ; i++) { if(apExists(m[i].getMacAddr())) { unsigned int ap_idx = apIndex(m[i].getMacAddr()); ap_power = access_point_list[ap_idx].getOutputPower(); ap_coords = access_point_list[ap_idx].getCoordinates(); ap_freq = access_point_list[ap_idx].getFrequency(); ap_gain = access_point_list[ap_idx].getAntennaGain(); ap_mac = access_point_list[ap_idx].getApAddr(); /* Compute main general term, independant from scans */ const_term = calib_gain + ap_gain; const_term -= 20 * log10(4 * M_PI); const_term += 20 * log10 (300000000.0 / ap_freq) + ap_power; if (reference_point_list[j].getPowerForAp(ap_mac, &mes_power)) friis_idx_list.push_back((const_term - mes_power) / (10 * log10(ap_coords.distance(pt_coords)))); else friis_idx_list.push_back(-1); cout << "AP " << m[i].getMacAddr() << " has Friis index: " << friis_idx_list[i] << endl; } } break; } } #ifdef DEBUG_T cout << "//<-- Server::computeFriisFromRefList(&Point, &vector)" << endl ; fflush(stdout) ; #endif // DEBUG_T return friis_idx_list; } /* Ajoute un client (ClientInfo) à la liste "client_list", et renvoie une référence sur l'élément ajouté. */ ClientInfo& Server::createClient() { #ifdef DEBUG_T cout << "//--> Server::createClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T client_list.push_back(ClientInfo()) ; #ifdef DEBUG_T cout << "//<-- Server::createClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T return client_list.back() ; } /* Localise le client d'identifiant "client_id" en appliquant l'algorithme voulu. */ void Server::monitorClient(const unsigned int &client_id, const ALGORITHM &algo) { #ifdef DEBUG_T cout << "//--> Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T if (VITERBI_N < 2) { cerr << "monitorClient() : N ne peut être inférieur à 2 !" << endl ; #ifdef DEBUG_T cout << "//<-- Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T return ; } vector &E_current = client_list[client_id].getRef_viterbi_Ecurrent(), &E_previous = client_list[client_id].getRef_viterbi_Eprevious() ; Point position ; float_array dst_matrix ; vector friisFromList; Point pointFastViterbi; Point Frbhmbasique; string filename = "trajet.txt"; ofstream fichier; #ifdef TEST vector peregrination_point_list ; makePointListFromFile(peregrination_point_list, DEFAULT_TRACKING_FILE, false) ; #endif // TEST #ifdef DEBUG cout << reference_point_list.size() << " points de référence" ; #ifdef TEST cout << ", " << peregrination_point_list.size() << " points de pérégrination." << endl ; #else // TEST cout << '.' << endl ; #endif // TEST #endif // DEBUG #ifdef DEBUG_2 cout << "***** Liste des points de référence : *****" << endl ; printReferencePointList() ; #ifdef TEST cout << "***** Liste des points de pérégrination : *****" << endl ; printPointList(peregrination_point_list) ; #endif // TEST cout << "*********************************" << endl ; #endif // DEBUG_2 #ifdef TEST unsigned int pt = 0 ; while (pt < peregrination_point_list.size()) #else // TEST while (true) #endif // TEST { vector vm ; #ifdef TEST /* Get point measurements */ //vm.clear(); vm = peregrination_point_list[pt].getMeasurementList(); #else // TEST vm = récupère_mesure() ; // FIXME ! #endif // TEST E_previous = E_current ; E_current = getkClosestInSs(vm, VITERBI_K) ; // Création de l'ensemble des K points les plus proches dans l'espace des puissances. #ifdef DEBUG cout << "Point courant : " << peregrination_point_list[pt] ; #endif // DEBUG switch (algo) { case ALGO_VLI : /* Application de l'algorithme Viterbi */ computeEuclideanDistances(&dst_matrix, E_previous, E_current) ; // On précalcule les distances entre les points de E_previous et E_current. position = fastViterbiLike(client_id, dst_matrix) ; break ; case ALGO_BASIC_FRBHM : /* Application de l'algorithme FRBHM basique */ cout << "-------FRBHM BASIQUE---------" << endl ; //computeFriisFromRefList() ; selectDistances(&dst_matrix, E_previous, E_current) ; // On récupère une sous-matrice de reference_point_matrix avec les distances entre les points de E_previous et E_current. position = fastViterbiLike(client_id, dst_matrix) ; cout << "Position: " << position << endl; friisFromList = computeFriisFromRefList(position, vm) ; //fbcm_friis(vm, friisFromList) ; //Just to see cout << "---------------------------" << endl; for(unsigned int i = 0 ; i < access_point_list.size() ; i ++) cout << "Dist between ap " << access_point_list[i].getCoordinates() << " and true point = " << access_point_list[i].getCoordinates().distance(peregrination_point_list[pt].getCoordinates()) << endl; //end of 'just to see' Frbhmbasique = fbcm_friis(vm, friisFromList, position.getZ()); cout << "Point selectionné final: " << Frbhmbasique << endl; fichier.open(filename.c_str(), std::ios::app); if ( !fichier ){ cerr << "Erreur de creation du fichier" << endl; exit(1); } fichier << Frbhmbasique << std::endl; fichier.close(); break ; case ALGO_CONTINU_FRBHM : /* Application de l'algorithme FRBHM continu */ cout << "--------FRBHM CONTINU------------" << endl ; //computeFriisFromRefList(); //Just to see cout << "---------------------------" << endl; for(unsigned int i = 0 ; i < access_point_list.size() ; i ++) cout << "Dist between ap " << access_point_list[i].getCoordinates() << " and true point " << peregrination_point_list[pt].getCoordinates() << " = " << access_point_list[i].getCoordinates().distance(peregrination_point_list[pt].getCoordinates()) << endl; //end of 'just to see' for (unsigned int i = 0 ; i < E_current.size() ; i++) { friisFromList = computeFriisFromRefList(E_current[i], vm) ; E_current[i] = fbcm_friis(vm, friisFromList,E_current[i].getZ()) ; } computeTopologyDistances(&dst_matrix, E_previous, E_current) ; // On calcule les distances entre les points de E_previous et E_current, en tenant compte de la topologie). pointFastViterbi = fastViterbiLike(client_id, dst_matrix) ; fichier.open(filename.c_str(), std::ios::app); cout << "Point selectionné: " << pointFastViterbi << endl; if ( !fichier ){ cerr << "Erreur de creation du fichier" << endl; exit(1); } fichier << pointFastViterbi << endl; fichier.close(); break; default : cerr << "Erreur ! Algorithme inconnu." << endl ; } #ifdef TEST pt++ ; #endif // TEST } #ifdef DEBUG_T cout << "//<-- Server::monitorClient()" << endl ; fflush(stdout) ; #endif // DEBUG_T } /* * Computes new cumulative distances for the viterbi instance of the client nb "client_id". * Returns the solution (Point) of the last ended viterbi. * Distances are grouped by line corresponding to an instance. */ Point Server::fastViterbiLike(const unsigned int &client_id, const float_array &distance_matrix) { #ifdef DEBUG_T cout << "//--> Server::fastViterbiLike()" << endl ; fflush(stdout) ; #endif // DEBUG_T float_array &V = client_list[client_id].getRef_viterbi_V() ; vector &E_current = client_list[client_id].getRef_viterbi_Ecurrent() ; unsigned int &i = client_list[client_id].getRef_viterbi_iteration() ; int N = VITERBI_N, K = VITERBI_K ; unsigned int V0_min_k = 0 ; // Indice du point sélectionné à chaque itération if (i > 1) // Si on n'est plus à la première itération { /* Recalcul des plus courtes distances */ for (float_index n = N-1-i ; n < N-2 ; n++) // Pour chaque historique existant (sauf le dernier), for (float_index k = 0 ; k < K ; k++) // pour chaque point de l'historique, { // on met à jour le chemin minimum entre l'historique précédent et le point : V[n][k] = V[n+1][0] + distance_matrix[0][k] ; for (float_index l = 1 ; l < K ; l++) { float f = V[n+1][l] + distance_matrix[l][k] ; if (f < V[n][k]) V[n][k] = f ; } } /* Traitement du dernier historique */ for (float_index k = 0 ; k < K ; k++) // Pour chaque point, { // on récupère le chemin minimum entre l'historique précédent et le point : V[N-2][k] = distance_matrix[0][k] ; for (float_index l = 1 ; l < K ; l++) { float f = distance_matrix[l][k] ; if (f < V[N-2][k]) V[N-2][k] = f ; } } /* Choix du point à renvoyer */ V0_min_k = 0 ; // Indice du point correspondant au V0 minimal. Si le tableau n'est pas plein, la plus petite valeur a l'indice 0 (car getkClosestInSs() renvoit un résultat trié). if (N-1-i == 0) { #ifdef DEBUG float V0_min = V[0][0] ; cout << "V[0][0]=" << V[0][0] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; #endif // DEBUG for (float_index k=1 ; k < K ; k++) { if (V[0][k] < V0_min) { V0_min_k = k ; #ifdef DEBUG V0_min = V[0][k] ; #endif // DEBUG } #ifdef DEBUG cout << "V[0][" << k << "]=" << V[0][k] << " ; V0_min=" << V0_min << " ; V0_min_k=" << V0_min_k << " -- " ; #endif // DEBUG } #ifdef DEBUG cout << "V0_min = " << V0_min << " ; V0_min_k=" << V0_min_k << endl ; #endif // DEBUG } } #ifdef DEBUG cout << "V :" << endl ; for (float_index n=0 ; n < N-1 ; n++) { for (float_index k=0 ; k < K ; k++) cout << "[" << V[n][k] << "]" ; cout << endl ; } cout << "Point sélectionné : " << E_current[V0_min_k] << endl ; cout << "--------------------------" << endl ; #endif // DEBUG if (i < N-1) i++ ; #ifdef DEBUG_T cout << "//<-- Server::fastViterbiLike()" << endl ; fflush(stdout) ; #endif // DEBUG_T return E_current[V0_min_k] ; } /* For experimentation purpose only */ void Server::radar_exp(const string &outfile, const string &testfile) { string fname; ofstream logfile; Point solution, solution_kw, ref_coords; unsigned int i; vector vm; computeFriisFromRefList() ; if (client_list.empty()) { #ifdef DEBUG cout << "radar_exp() : création d'un client." << endl ; #endif // DEBUG createClient() ; } logfile.open(outfile.c_str()); if (logfile.fail()) { cerr << "Error opening output file « " << logfile << " » !" << endl ; return ; } /* Column names */ logfile << "Coordinates\ \tInterlink\t(Error)\ \tRADAR\t(Error)\ \tFBCM\t(Error)\ \tFRBHM\t(Error)" << endl ; cout << reference_point_list.size() << " reference points." << endl ; vector test_point_list ; makePointListFromFile(test_point_list, DEFAULT_REF_POINT_FILE_1M, true) ; cout << test_point_list.size() << " reference points to test." << endl ; float radar_error = 0, in_error = 0, fbcm_error = 0, frbhm_error = 0; for (i = 0 ; i < test_point_list.size() ; i++) { /* Get point measurements */ vm = test_point_list[i].getMeasurementList(); cout << vm.size() << " measurements:" << endl ; for(unsigned int prout = 0 ; prout < vm.size() ; prout++) cout << vm[prout] << endl; ref_coords = test_point_list[i].getCoordinates(); /* Print point coordinates */ logfile << ref_coords << "\t"; /* Interlink Networks */ solution = interlink(vm, 0) ; logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; in_error += solution.distance(ref_coords); /* RADAR */ solution = getkClosestInSs(vm, 1, &ref_coords)[0] ; logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; radar_error += solution.distance(ref_coords); /* FBCM */ solution = fbcm(vm, 0) ; logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; fbcm_error += solution.distance(ref_coords); /* 1-NSS + FBCM */ solution = getkClosestInSs(vm, 1, &ref_coords)[0] ; solution = fbcm_friis(vm, computeFriisFromRefList(solution, vm), solution.getZ()) ; logfile << solution << "\t" << solution.distance(ref_coords) << "\t" ; frbhm_error += solution.distance(ref_coords); // /* 2-NSS */ // solution = getkWeightedInSs(vm, 2, &ref_coords); // logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; // /* 3-NSS */ // solution = getkWeightedInSs(vm, 3, &ref_coords); // logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; // /* 5-NSS */ // solution = getkWeightedInSs(vm, 5, &ref_coords); // logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; logfile << endl ; vm.clear() ; } /* Mean values formulas names */ float nb = (float) test_point_list.size(); logfile << "\t\t" << (in_error / nb) << "\t\t" << (radar_error / nb) << "\t\t" << (fbcm_error / nb) << "\t\t" << (frbhm_error / nb) << endl ; logfile.close(); }