#include "server.hh" #define TEST #define DEBUG // Décommenter pour avoir de l'affichage en plus. //#define DEBUG_2 // Décommenter pour avoir encore plus d'affichage. /******* Misc. very usefull functions *******/ /* 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 &ip_addr, const int &listen_port) { /* 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)); makeReferencePointListFromFile(DEFAULT_REF_POINT_FILE); makeApListFromFile(DEFAULT_AP_FILE); } Server::~Server() { client_list.clear(); reference_point_list.clear(); access_point_list.clear(); close(sockListen); close(sockSend); } 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; } /* 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. */ bool Server::pointExists(const float &x, const float &y, const float &z)const { return pointExists(reference_point_list, Point(x, y, z)) ; } /* FONCTION POUR RÉTRO-COMPATIBILITÉ. * Recherche un Point dans la liste reference_point_list, retourne true s'il existe, false sinon. */ bool Server::pointExists(const Point &p)const { return pointExists(reference_point_list, p) ; } /* Recherche un point de coordonnées (x;y;z) dans la liste "point_list", retourne true s'il existe, false sinon. */ bool Server::pointExists(const vector &point_list, const float &x, const float &y, const float &z) const { return pointExists(point_list, Point(x, y, z)) ; } /* Recherche un Point dans la liste "point_list", retourne true s'il existe, false sinon. */ bool Server::pointExists(const vector &point_list, const Point &p) const { unsigned int i; for (i = 0 ; i < point_list.size() ; i++) if (p == point_list[i].getCoordinates()) return true; return false; } /* Do not forget to call pointExists() before this one */ unsigned int Server::pointIndex(const float &x, const float &y, const float &z)const { return pointIndex(reference_point_list, Point(x, y, z)) ; } /* Do not forget to call pointExists() before this one */ unsigned int Server::pointIndex(const Point &p)const { return pointIndex(reference_point_list, p) ; } unsigned int Server::pointIndex(const vector &point_list, const float &x, const float &y, const float &z) const { return pointIndex(point_list, Point(x, y, z)) ; } unsigned int Server::pointIndex(const vector &point_list, const Point &p) const { unsigned int i; for (i = 0 ; i < reference_point_list.size() ; i++) if (p == reference_point_list[i].getCoordinates()) return i; return 0; // Should never happen } bool Server::apExists(const string &ap_addr)const { unsigned int i; for (i = 0 ; i < access_point_list.size() ; i++) if (access_point_list[i].getApAddr() == ap_addr) return true; return false; } unsigned int Server::apIndex(const string &ap_addr)const { unsigned int i; for (i = 0 ; i < access_point_list.size() ; i++) if (access_point_list[i].getApAddr() == ap_addr) return i; 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 { 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 { 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); /* 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 */ } } /* 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() - 1 ; i++) cout << distances_vector[i] << " : " << points_vector[i] << endl ; #endif // DEBUG return points_vector; } Point Server::getkWeightedInSs(const vector &m, const unsigned int &k)const { return getkWeightedInSs(m, k, NULL) ; } /* 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 { 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 += distances_vector[i]; for (i = 0 ; i < distances_vector.size() ; i++) { x += points_vector[i].getX() * distances_vector[i] / total; y += points_vector[i].getY() * distances_vector[i] / total; z += points_vector[i].getZ() * distances_vector[i] / total; } ret.setX(x); ret.setY(y); ret.setZ(z); return ret; } Point Server::kPointsAverage(const vector &vp)const { 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()); return p; } Point Server::fbcm(const vector &m, const int &client_idx)const { 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; 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) { minmax_max = 0; for (i = 0 ; i < centres.size() ; i++) if ((centres[i].squareDistance(x, y, 3) - (dist_vect[i]*dist_vect[i])) > minmax_max) minmax_max = centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i]); if (minmax_max < minmax_res) { ret.setX(x); ret.setY(y); minmax_res = minmax_max; } } /* Clear all vectors */ addr.clear(); dist_vect.clear(); centres.clear(); /* Return position */ return ret; } Point Server::interlink(const vector &m, const int &client_idx)const { 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; 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) { minmax_max = 0; for (i = 0 ; i < centres.size() ; i++) if ((centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i])) > minmax_max) minmax_max = centres[i].squareDistance(x, y, 3) - (dist_vect[i] * dist_vect[i]) ; if (minmax_max < minmax_res) { ret.setX(x); ret.setY(y); minmax_res = minmax_max; } } /* Clear all vectors */ addr.clear(); dist_vect.clear(); centres.clear(); /* 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) { makePointListFromFile(reference_point_list, filename, true) ; } void Server::makePointListFromFile(vector &dest_point_list, const string &filename) { makePointListFromFile(dest_point_list, filename, true) ; } /* 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) { 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() ; } void Server::makeApListFromFile(const string &filename) { 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(); } /* FONCTION POUR RÉTRO-COMPATIBILITÉ * Affiche la liste des points de référence (reference_point_list). */ void Server::printReferencePointList() { printPointList(reference_point_list) ; } /* Affiche une liste de points (point_list). */ void Server::printPointList(vector &point_list) { for (unsigned int i = 0 ; i < point_list.size() ; i++) cout << point_list[i] << endl ; } void Server::printAccessPointList() { for (unsigned int i = 0 ; i < access_point_list.size() ; i++) cout << access_point_list[i] << endl; } void Server::computeFriisFromRefList() { 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(); } } /* * Computes new cumulative distances for each running viterbi instance, * Returns the solution (type: Point) of the last ended viterbi. * Distances are grouped by line corresponding to an instance. * "K" MUST be the same as last.size() and current.size() ! */ void Server::fastViterbiLike(const unsigned short &N, const unsigned short &K, const unsigned int &id_client) { #ifdef TEST ClientInfo cl ; float **V = cl.get_viterbi_V() ; vector &E_current = cl.getRef_viterbi_Ecurrent(), &E_previous = cl.getRef_viterbi_Eprevious() ; vector peregrination_point_list ; makePointListFromFile(peregrination_point_list, DEFAULT_TRACKING_FILE, false) ; #else // TEST float **V = client_list[id_client].get_viterbi_V() ; vector &E_current = client_list[id_client].getRef_viterbi_Ecurrent(), &E_previous = client_list[id_client].getRef_viterbi_Eprevious() ; #endif // TEST int i = 1 ; // Nombre d'ensembles d'historique qu'on a déjà passés if (N < 2) { cerr << "fastViterbiLike() : N ne peut être inférieur à 2 !" << endl ; return ; } #ifdef TEST unsigned int pt = 0 ; #ifdef DEBUG cout << reference_point_list.size() << " points de référence, " << peregrination_point_list.size() << " points de pérégrination." << endl ; cout << "***** Liste pts référence : *****" << endl ; printReferencePointList() ; cout << "***** Liste pérégrination : *****" << endl ; printPointList(peregrination_point_list) ; cout << "*********************************" << endl ; #endif // DEBUG 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(); #endif // TEST E_previous = E_current ; E_current = getkClosestInSs(vm, 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 if (i > 1) // Si on n'est plus à la première itération { /* Recalcul des plus courtes distances */ for (int n = N-1-i ; n < N-2 ; n++) // Pour chaque historique existant (sauf le dernier), for (int 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] + E_previous[0].distance(E_current[k]) ; for (int l = 1 ; l < K ; l++) { float f = V[n+1][l] + E_previous[l].distance(E_current[k]) ; if (f < V[n][k]) V[n][k] = f ; } } /* Traitement du dernier historique */ for (int 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] = E_previous[0].distance(E_current[k]) ; for (int l = 1 ; l < K ; l++) { float f = E_previous[l].distance(E_current[k]) ; if (f < V[N-2][k]) V[N-2][k] = f ; } } /* Choix du min à renvoyer */ if (N-1-i == 0) { float V0_min = V[0][0] ; for (int k=1 ; k < K ; k++) { if (V[0][k] < V0_min) V0_min = V[0][k] ; cout << "V[0][" << k << "]=" << V[0][k] << " ; V0_min=" << V0_min << " -- " ; } cout << "V0_min = " << V0_min << endl ; } } #ifdef DEBUG // cout << "(N=" << N << ") - 1 - (i=" << i << ") = " << N-1-i << endl ; cout << "V :" << endl ; for (int n=0 ; n < N-1 ; n++) { for (int k=0 ; k < K ; k++) cout << "[" << V[n][k] << "]" ; cout << endl ; } cout << "\n--------------------------" << endl ; #endif // DEBUG if (i < N-1) i++ ; #ifdef TEST pt++ ; #endif // TEST } } /* For experimentation purpose only */ void Server::radar_exp() { ofstream logfile; vector solutions; Point solution, solution_kw, ref_coords; unsigned int i; vector vm; // computeFriisFromRefList(); /* Open a log file */ logfile.open(DEFAULT_LOGFILE); if (logfile.fail()) { cerr << "Error opening output file « " << logfile << " » !" << endl ; return ; } /* Column names */ logfile << "Coordinates\t2-kss\t(Error)\t3-kss\t(Error)\t4-kss\t(Error)\t5-kss\t(Error)\tnss\t(Error)\tInterlink\t(Error)\tFBCM\t(Error)" << endl; cout << reference_point_list.size() << " reference points." << endl ; for (i = 0 ; i < reference_point_list.size() ; i++) { /* Get point measurements */ vm.clear(); vm = reference_point_list[i].getMeasurementList(); ref_coords = reference_point_list[i].getCoordinates(); /* Print point coordinates */ logfile << ref_coords << "\t"; /* From 2 to 5 K-weighted-SS */ solution = getkWeightedInSs(vm, 2, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 3, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 4, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; solution = getkWeightedInSs(vm, 5, &ref_coords); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; /* Nearest in SS */ solutions = getkClosestInSs(vm, 1, &ref_coords); logfile << solutions[0] << "\t" << solutions[0].distance(ref_coords) << "\t"; /* Interlink Networks */ solution = interlink(vm, 0); logfile << solution << "\t" << solution.distance(ref_coords) << "\t"; /* FBCM */ solution = fbcm(vm, 0); logfile << solution << "\t" << solution.distance(ref_coords) << endl; solutions.clear(); } logfile.close(); }