owlps/owlps-positioning/server.cc

2546 lines
73 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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".
/* *** À commenter pour utiliser les mesures centrées mobile de Fred */
if (! checkTopology()) // Vérifications.
{
cerr << "Topology flawed. Exiting program." << endl ;
exit(1) ; // Si problème, on quitte.
}
/* Fin du bloc à commenter *** */
makeReferencePointDistances() ; // Initialisation de "reference_point_matrix".
makeApListFromFile(ap_file.c_str()) ; // Initialisation de "access_point_list".
#ifdef DEBUG_T
cout << "//<-- Server::Server()" << endl ; fflush(stdout) ;
#endif // DEBUG_T
}
Server::~Server()
{
#ifdef DEBUG_T
cout << "//--> Server::~Server()" << endl ; fflush(stdout) ;
#endif // DEBUG_T
close(sockListen);
close(sockSend);
reference_point_list.clear();
access_point_list.clear();
client_list.clear();
#ifdef DEBUG_T
cout << "//<-- Server::~Server()" << endl ; fflush(stdout) ;
#endif // DEBUG_T
}
void Server::send_to_client(const int &cl)
{
/* Do not forget to implement later: usefull for a demo */
}
int Server::receive_data()
{
/* Do not forget to implement later: usefull for a demo */
return 0;
}
/* Cherche dans quelle(s) zone(s) se situe un point.
* Retourne une map<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();
}