2544 lines
73 KiB
C++
2544 lines
73 KiB
C++
#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<string> explode(const string &input, const char &sep)
|
||
{
|
||
vector<string> 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<int> extractValues(string buff)
|
||
{
|
||
unsigned int ptr = 0;
|
||
vector<int> 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<string> extractReferencePointInfoFromBuffer(const string &buffer_in)
|
||
{
|
||
unsigned int i = 0;
|
||
string tmp_field;
|
||
vector<string> 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".
|
||
|
||
/*if (! checkTopology()) // Vérifications.
|
||
{
|
||
cout << "Topology flawed.\nExiting program." << endl ;
|
||
exit(1) ; // Si problème, on quitte.
|
||
}*/
|
||
|
||
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<string, Area> contenant la liste des zones auxquelles le Point "p" appartient.
|
||
*/
|
||
map<string, Area> Server::inWhichAreas(const Point &p)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::inWhichAreas()" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
map<string, Area> areas ;
|
||
|
||
for (map<string, Area>::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<string, Area> // Liste des zones comportant les points p1 et p2 :
|
||
zones1(inWhichAreas(p1)),
|
||
zones2(inWhichAreas(p2)) ;
|
||
|
||
#ifdef DEBUG_2
|
||
cout << " zones1 (" << zones1.size() << ") : [" ;
|
||
for (map<string, Area>::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++)
|
||
cout << it1->first << ',' ;
|
||
cout << "\b]" ;
|
||
cout << " zones2 (" << zones2.size() << ") : [" ;
|
||
for (map<string, Area>::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<string, Area>::iterator it1 = zones1.begin() ; it1 != zones1.end() ; it1++) // Parcours des zones :
|
||
for (map<string, Area>::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<Point> contenant la liste de ces points.
|
||
*/
|
||
vector<Point> Server::areaConnection(const Area &z1, const Area &z2)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::areaConnection(Area&, Area&)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
vector<Point> points ;
|
||
|
||
for (unsigned int i = 0 ; i < waypoint_list.size() ; i++)
|
||
{
|
||
map<string, Area> 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<Point> contenant la liste de ces points.
|
||
*/
|
||
vector<Point> Server::areaConnection(const Area &z)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::areaConnection(Area&)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
vector<Point> points ;
|
||
|
||
for (unsigned int i = 0 ; i < waypoint_list.size() ; i++)
|
||
{
|
||
map<string, Area> 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<string, Area>
|
||
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<Point> 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<Point> // 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<ReferencePoint> &point_list, const float &x, const float &y, const float &z) const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::pointExists(&vector<ReferencePoint>, &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<ReferencePoint>, &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<ReferencePoint> &point_list, const Point &p) const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::pointExists(&vector<ReferencePoint>, &Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
bool ret = (pointIndex(point_list, p) != -1) ;
|
||
|
||
#ifdef DEBUG_T
|
||
cout << "//<-- Server::pointExists(&vector<ReferencePoint>, &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<ReferencePoint> &point_list, const float &x, const float &y, const float &z) const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::pointIndex(&vector<ReferencePoint>, &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<ReferencePoint>, &float, &float, &float)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
return ret ;
|
||
}
|
||
|
||
|
||
|
||
inline int Server::pointIndex(const vector<ReferencePoint> &point_list, const Point &p) const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::pointIndex(&vector<ReferencePoint>, &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<ReferencePoint>, &Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
return i ;
|
||
}
|
||
|
||
#ifdef DEBUG_T
|
||
cout << "//<-- Server::pointIndex(&vector<ReferencePoint>, &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> &point_list, const Point &p) const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::pointIndex(&vector<Point>, &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>, &Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
return i ;
|
||
}
|
||
|
||
#ifdef DEBUG_T
|
||
cout << "//<-- Server::pointIndex(&vector<Point>, &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<Point> Server::getkClosestInSs(const vector<Measurement> &m, const unsigned int &k)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::getkClosestInSs(&vector<Measurement>, &unsigned int)" << endl ;
|
||
cout << "//<-- Server::getkClosestInSs(&vector<Measurement>, &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<Point> Server::getkClosestInSs(const vector<Measurement> &m, const unsigned int &k, const Point *point_ignored)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::getkClosestInSs(&vector<Measurement>, &unsigned int, *Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
unsigned int i, j, min_idx;
|
||
vector<float> distances_vector;
|
||
vector<Point> 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<Measurement>, &unsigned int, *Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
return points_vector;
|
||
}
|
||
|
||
|
||
|
||
Point Server::getkWeightedInSs(const vector<Measurement> &m, const unsigned int &k)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::getkWeightedInSs(&vector<Measurement>, &unsigned int)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
Point ret = getkWeightedInSs(m, k, NULL) ;
|
||
|
||
#ifdef DEBUG_T
|
||
cout << "//<-- Server::getkWeightedInSs(&vector<Measurement>, &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<Measurement> &m, const unsigned int &k, const Point *point_ignored)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::getkWeightedInSs(&vector<Measurement>, &unsigned int, *Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
unsigned int i, j;
|
||
vector<float> distances_vector;
|
||
vector<Point> 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<Measurement>, &unsigned int, *Point)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
|
||
Point Server::kPointsAverage(const vector<Point> &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<Measurement> &m, const int &client_idx)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::fbcm()" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
Point ret(0, 0, 0);
|
||
vector<string> addr;
|
||
vector<float> dist_vect;
|
||
vector<Point> 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<Measurement> &m and a list of friis index*/
|
||
Point Server::fbcm_friis( const vector<Measurement> &m, const vector<float> 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<string> addr;
|
||
vector<float> dist_vect;
|
||
vector<Point> centres;
|
||
unsigned int i, j, ap_idx;
|
||
float constant_term, minmax_res, minmax_max;
|
||
float x = MINMAX_X_START, y = MINMAX_Y_START ;
|
||
vector<Measurement> vm = m; //Used when filtering 3 strongest APs
|
||
vector<float> 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] <<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 (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();
|
||
//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<Measurement> &m, const int &client_idx)const
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::interlink()" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
Point ret(0, 0, 0);
|
||
vector<string> addr;
|
||
vector<float> dist_vect;
|
||
vector<Point> 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<ReferencePoint> &dest_point_list, const string &filename)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::makePointListFromFile(&vector<ReferencePoint>, &string)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
makePointListFromFile(dest_point_list, filename, true) ;
|
||
|
||
#ifdef DEBUG_T
|
||
cout << "//<-- Server::makePointListFromFile(&vector<ReferencePoint>, &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<ReferencePoint> &dest_point_list, const string &filename, const bool uniq_point)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::makePointListFromFile(&vector<ReferencePoint>, &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<string> 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<int> 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<ReferencePoint>, &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<string> 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<string> 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<string, Area>::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<string> infos ;
|
||
set<Point> 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<Point>::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<string, Area> 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<string, Area>::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<string, Area> 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<string, Area>::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<string> 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<string, Area>::iterator it1 = area_list.begin() ; it1 != area_list.end() ; it1++)
|
||
for (map<string, Area>::iterator it2 = area_list.begin() ; it2 != area_list.end() ; it2++)
|
||
{
|
||
if (it1 == it2)
|
||
continue ;
|
||
|
||
vector<Point> 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<string, Area> 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<string>::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<string, Area>::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<Point> &l1, const vector<Point> &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<Point> &l1, const vector<Point> &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<Point> &l1, const vector<Point> &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<ReferencePoint> &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<float> 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<float> Server::computeFriisFromRefList(const Point &p, const vector<Measurement> &m)
|
||
{
|
||
#ifdef DEBUG_T
|
||
cout << "//--> Server::computeFriisFromRefList(&Point, &vector<Measurement>)" << endl ; fflush(stdout) ;
|
||
#endif // DEBUG_T
|
||
|
||
vector<float> 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<Measurement>)" << 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<Point>
|
||
&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<float> friisFromList;
|
||
Point pointFastViterbi;
|
||
Point Frbhmbasique;
|
||
string filename = "trajet.txt";
|
||
ofstream fichier;
|
||
|
||
#ifdef TEST
|
||
vector<ReferencePoint> 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<Measurement> 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<Point> &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<Measurement> 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<ReferencePoint> 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();
|
||
}
|