owlps/owlps-positioning/src/stock.cc

292 lines
7.2 KiB
C++

#include "stock.hh"
#include "posexcept.hh"
using namespace std ;
using std::tr1::unordered_map ;
using std::tr1::unordered_set ;
/* *** Attribute definitions *** */
unordered_map<string, Building> Stock::buildings ;
unordered_map<Point3D, Waypoint> Stock::waypoints ;
unordered_map<string, Mobile> Stock::mobiles ;
unordered_map<string, AccessPoint> Stock::aps ;
unordered_set<ReferencePoint> Stock::reference_points ;
unordered_set<CalibrationRequest> Stock::calibration_requests ;
void Stock::clear()
{
buildings.clear() ;
// Waypoints are normally deleted in Building::~Building(), so we must
// not clear waypoints before buildings, but we clear it *after*, just
// in case.
waypoints.clear() ;
mobiles.clear() ;
aps.clear() ;
reference_points.clear() ;
calibration_requests.clear() ;
}
/* *** Building operations *** */
/**
* The name of the Building is initialised.
*/
const Building& Stock::find_create_building(const string &name)
{
unordered_map<string, Building>::const_iterator i =
buildings.find(name) ;
if (i != buildings.end())
return i->second ;
Building &building = buildings[name] ;
building.set_name(name) ;
return building ;
}
/**
* @param name The name of the Building to search for.
* It must be a valid name, as no check is performed.
* @return A const reference to the Building.
* @throw element_not_found is thrown if the Building corresponding
* to \em name does not exist.
*/
const Building& Stock::get_building(const string &name)
{
unordered_map<string, Building>::const_iterator i =
buildings.find(name) ;
if (i != buildings.end())
return i->second ;
throw element_not_found("No Building with name « " + name + " »!") ;
}
/* *** Waypoint operations *** */
const Waypoint& Stock::
find_create_waypoint(const Point3D &point)
{
unordered_map<Point3D, Waypoint>::const_iterator i =
waypoints.find(point) ;
if (i != waypoints.end())
return i->second ;
Waypoint &waypoint = waypoints[point] ;
waypoint.set_coordinates(point) ;
return waypoint ;
}
void Stock::waypoint_remove_building(const Waypoint &point,
const Building *building)
{
unordered_map<Point3D, Waypoint>::iterator i =
waypoints.find(point) ;
Waypoint *waypoint = const_cast<Waypoint*>(&i->second) ;
waypoint->remove_building(building) ;
// If the Waypoint is not linked to any Building any more, we
// delete it
if (waypoint->get_1st_building() == NULL)
waypoints.erase(i) ;
}
/* *** Mobile operations *** */
/**
* @param mac The MAC address of the Mobile to search for.
* It must be a valid MAC address, as no check is performed.
* @return A const reference to the Mobile.
* @throw element_not_found is thrown if the Mobile corresponding
* to \em mac does not exist.
*/
const Mobile& Stock::get_mobile(const string &mac)
{
unordered_map<string, Mobile>::const_iterator i = mobiles.find(mac) ;
if (i != mobiles.end())
return i->second ;
throw element_not_found("No Mobile with MAC address « " +
mac + " »!") ;
}
/**
* If created, the MAC address of the Mobile is initialised.
*/
const Mobile& Stock::find_create_mobile(const string &mac)
{
unordered_map<string, Mobile>::const_iterator i = mobiles.find(mac) ;
if (i != mobiles.end())
return i->second ;
Mobile &mobile = mobiles[mac] ;
mobile.set_mac_addr(mac) ;
return mobile ;
}
/* *** AccessPoint operations *** */
/**
* @param mac The MAC address of the AccessPoint to search for.
* It must be a valid MAC address, as no check is performed.
* @return A const reference to the AccessPoint.
* @throw element_not_found is thrown if the AccessPoint corresponding
* to \em mac does not exist.
*/
const AccessPoint& Stock::get_ap(const string &mac)
{
unordered_map<string, AccessPoint>::const_iterator i = aps.find(mac) ;
if (i != aps.end())
return i->second ;
throw element_not_found("No AccessPoint with MAC address « " +
mac + " »!") ;
}
/**
* The MAC address of the AccessPoint is initialised.
*/
const AccessPoint& Stock::find_create_ap(const string &mac)
{
unordered_map<string, AccessPoint>::const_iterator i = aps.find(mac) ;
if (i != aps.end())
return i->second ;
AccessPoint &ap = aps[mac] ;
ap.set_mac_addr(mac) ;
return ap ;
}
/**
* If the AccessPoint already exists, it is replaced by the \em source.
*/
const AccessPoint& Stock::find_create_ap(const AccessPoint &source)
{
const string &mac = source.get_mac_addr() ;
unordered_map<string, AccessPoint>::const_iterator i = aps.find(mac) ;
if (i != aps.end())
return i->second ;
aps[mac] = source ;
return aps[mac] ;
}
void Stock::update_all_friis_indexes()
{
for (unordered_map<string, AccessPoint>::iterator ap = aps.begin() ;
ap != aps.end() ; ++ap)
{
string ap_mac = ap->second.get_mac_addr() ;
double friis_idx_sum = 0 ;
int nb_friis_idx = 0 ;
// Compute main general term, independant from scans
double ap_freq = ap->second.get_frequency() ;
double const_term =
ap->second.get_antenna_gain()
- 20 * log10(4 * M_PI)
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
+ ap->second.get_trx_power() ;
/*
* Compute indexes for each ReferencePoint. The Friis index for an
* AP is the average of all indexes in all ReferencePoint.
*/
for (unordered_set<ReferencePoint>::const_iterator rp =
reference_points.begin() ; rp != reference_points.end() ;
++rp)
{
int nb_idx = 0 ;
float ap_friis_idx_sum =
rp->friis_indexes_for_ap(ap->second, const_term, nb_idx) ;
if (nb_idx != 0)
{
friis_idx_sum += ap_friis_idx_sum ;
nb_friis_idx += nb_idx ;
}
}
if (nb_friis_idx > 0)
ap->second.set_friis_index(friis_idx_sum / nb_friis_idx) ;
}
}
/* *** ReferencePoint operations *** */
const ReferencePoint& Stock::
find_create_reference_point(const ReferencePoint &point)
{
// unordered_set::insert() do all the job: see the documentation at
// http://boost.org/doc/libs/1_42_0/doc/html/boost/unordered_set.html
pair<unordered_set<ReferencePoint>::iterator, bool> ret =
reference_points.insert(point) ;
return *ret.first ;
}
const ReferencePoint& Stock::
closest_reference_point(const Request &request)
{
if (reference_points.empty())
throw element_not_found("Cannot search for the closest reference \
point: reference point list is empty!") ;
unordered_set<ReferencePoint>::const_iterator i =
reference_points.begin() ;
float distance = i->ss_square_distance(request) ;
unordered_set<ReferencePoint>::const_iterator closest = i ;
for (++i ; i != reference_points.end() ; ++i)
{
float tmp_distance = i->ss_square_distance(request) ;
if (tmp_distance < distance)
{
distance = tmp_distance ;
closest = i ;
}
}
return *closest ;
}
/* *** CalibrationRequest operations *** */
const CalibrationRequest& Stock::
find_create_calibration_request(const CalibrationRequest &request)
{
pair<unordered_set<CalibrationRequest>::iterator, bool> ret =
calibration_requests.insert(request) ;
return *ret.first ;
}