[Positioning] Add positioning algorithm Basic FRBHM

Add class FRBHMBasic, which derives FBCM and RADAR.

ReferencePoint: Add functions friis_index_for_ap() and
friis_indexes_for_ap() (that takes code away from
Stock::update_all_friis_indexes()).

CartographyAlgorithm and MultilaterationAlgorithm now extend
PositioningAlgorithm with "public virtual" instead of "public".

CartographyAlgorithm: select_point() must now return a ReferencePoint.

MultilaterationMethod: Add pure virtual function multilaterate_2d().

MinMax: Add function multilaterate_2d().

MultilaterationAlgorithm: Add function multilaterate_2d() to map
MultilaterationMethod::multilaterate_2d().

Makefile: Fix some dependencies.
This commit is contained in:
Matteo Cypriani 2010-06-14 17:15:48 +02:00
parent e12db08b0d
commit c731bf578f
18 changed files with 273 additions and 52 deletions

View File

@ -55,6 +55,7 @@ OBJ_LIST = \
minmax.o \
interlinknetworks.o \
fbcm.o \
frbhmbasic.o \
radar.o \
realposition.o \
configuration.o \
@ -196,6 +197,9 @@ $(OBJ_DIR)/multilaterationalgorithm.o: \
$(SRC_DIR)/positioningalgorithm.hh \
$(OBJ_DIR)/minmax.o \
$(OBJ_DIR)/mobile.o
$(OBJ_DIR)/cartographyalgorithm.o: \
$(SRC_DIR)/positioningalgorithm.hh \
$(OBJ_DIR)/referencepoint.o
$(OBJ_DIR)/minmax.o: \
$(SRC_DIR)/multilaterationmethod.hh \
$(OBJ_DIR)/point3d.o \
@ -204,6 +208,9 @@ $(OBJ_DIR)/interlinknetworks.o: \
$(OBJ_DIR)/multilaterationalgorithm.o
$(OBJ_DIR)/fbcm.o: \
$(OBJ_DIR)/multilaterationalgorithm.o
$(OBJ_DIR)/frbhmbasic.o: \
$(OBJ_DIR)/radar.o \
$(OBJ_DIR)/fbcm.o
$(OBJ_DIR)/radar.o: \
$(OBJ_DIR)/cartographyalgorithm.o
$(OBJ_DIR)/realposition.o: \
@ -215,8 +222,10 @@ $(OBJ_DIR)/positioning.o: \
$(OBJ_DIR)/inputdatareader.o \
$(OBJ_DIR)/input.o \
$(OBJ_DIR)/realposition.o \
$(OBJ_DIR)/radar.o \
$(OBJ_DIR)/fbcm.o \
$(OBJ_DIR)/frbhmbasic.o \
$(OBJ_DIR)/interlinknetworks.o \
$(OBJ_DIR)/radar.o \
$(OBJ_DIR)/output.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/posexcept.o

View File

@ -2,9 +2,10 @@
#define _OWLPS_POSITIONING_CARTOGRAPHYALGORITHM_HH_
#include "positioningalgorithm.hh"
#include "referencepoint.hh"
/// Super-class of SS cartography-based positioning algorithms
class CartographyAlgorithm: public PositioningAlgorithm
class CartographyAlgorithm: public virtual PositioningAlgorithm
{
public:
CartographyAlgorithm(void) {}
@ -13,7 +14,8 @@ public:
/** @name Operations */
//@{
Result compute(const Request &request) ;
virtual Point3D select_point(const Request &request) = 0 ;
virtual const ReferencePoint& select_point(
const Request &request) = 0 ;
//@}
} ;

View File

@ -8,5 +8,11 @@ float FBCM::estimate_distance(const Measurement &measurement)
const float &average_ss = measurement.get_average_ss() ;
const AccessPoint *ap = measurement.get_ap() ;
return pow(10, (constant_term - average_ss) /
(10 * ap->get_friis_index())) ;
(10 * friis_index(ap))) ;
}
inline float FBCM::friis_index(const AccessPoint *const ap) const
{
return ap->get_friis_index() ;
}

View File

@ -6,6 +6,9 @@
/// Computes a position using the Interlink Networks formula
class FBCM: public MultilaterationAlgorithm
{
protected:
float friis_index(const AccessPoint *const ap) const ;
public:
FBCM(void) {}
~FBCM(void) {}

View File

@ -0,0 +1,38 @@
#include "frbhmbasic.hh"
Result FRBHMBasic::compute(const Request &_request)
{
request = &_request ;
// Select the closest point in SS
closest_in_ss = &select_point(_request) ;
compute_ap_distance_circles() ;
Point3D position(multilaterate_2d(closest_in_ss->get_z())) ;
return Result(request, position) ;
}
/* TODO:
* It is ugly to duplicate this function from FBCM. We should find a
* trick to do it prettier. The thing is that FBCM::estimate_distance()
* will not call FRBHMBasic::friis_index() but FBCM::friis_index(),
* which is wrong in our case.
*/
float FRBHMBasic::estimate_distance(const Measurement &measurement)
{
double constant_term = make_constant_term(measurement) ;
const float &average_ss = measurement.get_average_ss() ;
const AccessPoint *ap = measurement.get_ap() ;
return pow(10, (constant_term - average_ss) /
(10 * friis_index(ap))) ;
}
inline float FRBHMBasic::friis_index(const AccessPoint *const ap) const
{
return closest_in_ss->friis_index_for_ap(ap->get_mac_addr()) ;
}

View File

@ -0,0 +1,25 @@
#ifndef _OWLPS_POSITIONING_FRBHMBASIC_HH_
#define _OWLPS_POSITIONING_FRBHMBASIC_HH_
#include "fbcm.hh"
#include "radar.hh"
/// Computes a position using the Interlink Networks formula
class FRBHMBasic: public FBCM, public RADAR
{
protected:
ReferencePoint const *closest_in_ss ;
float friis_index(const AccessPoint *const ap) const ;
public:
FRBHMBasic(void) {}
~FRBHMBasic(void) {}
/** @name Operations */
//@{
Result compute(const Request &_request) ;
float estimate_distance(const Measurement &measurement) ;
//@}
} ;
#endif // _OWLPS_POSITIONING_FRBHMBASIC_HH_

View File

@ -6,31 +6,51 @@ using std::tr1::unordered_map ;
Point3D MinMax::multilaterate(
const unordered_map<AccessPoint*, float> &ap_distances)
const unordered_map<AccessPoint*, float> &_ap_distances)
{
float min = INFINITE ;
Point3D centre(start) ;
min = INFINITE ;
centre = start ;
ap_distances = &_ap_distances ;
for (float x = start.get_x() ; x <= stop.get_x() ; x += step)
for (float y = start.get_y() ; y <= stop.get_y() ; y += step)
for (float z = start.get_z() ; z <= stop.get_z() ; z += step)
{
float d_max = 0 ;
for (unordered_map<AccessPoint*, float>::const_iterator i =
ap_distances.begin() ; i != ap_distances.end() ; ++i)
{
float dist =
Point3D(x, y, z).distance_to_sphere(
i->first->get_coordinates(), i->second) ;
if (dist > d_max)
d_max = dist ;
}
if (d_max <= min)
{
min = d_max ;
centre.set_coordinates(x, y, z) ;
}
}
iterate(x, y, z) ;
return centre ;
}
Point3D MinMax::multilaterate_2d(
const unordered_map<AccessPoint*, float> &_ap_distances, float z)
{
min = INFINITE ;
centre = start ;
ap_distances = &_ap_distances ;
for (float x = start.get_x() ; x <= stop.get_x() ; x += step)
for (float y = start.get_y() ; y <= stop.get_y() ; y += step)
iterate(x, y, z) ;
return centre ;
}
void MinMax::iterate(float x, float y, float z)
{
float d_max = 0 ;
for (unordered_map<AccessPoint*, float>::const_iterator i =
ap_distances->begin() ; i != ap_distances->end() ; ++i)
{
float dist =
Point3D(x, y, z).distance_to_sphere(
i->first->get_coordinates(), i->second) ;
if (dist > d_max)
d_max = dist ;
}
if (d_max <= min)
{
min = d_max ;
centre.set_coordinates(x, y, z) ;
}
}

View File

@ -6,6 +6,13 @@
/// Multilaterates using the Lassabe's MinMax algorithm
class MinMax: public MultilaterationMethod
{
private:
float min ;
Point3D centre ;
std::tr1::unordered_map<AccessPoint*, float> const *ap_distances ;
void iterate(float x, float y, float z) ;
protected:
const Point3D start ;
const Point3D stop ;
@ -23,7 +30,10 @@ public:
~MinMax(void) {}
Point3D multilaterate(
const std::tr1::unordered_map<AccessPoint*, float> &ap_distances) ;
const std::tr1::unordered_map<AccessPoint*, float> &_ap_distances) ;
Point3D multilaterate_2d(
const std::tr1::unordered_map<AccessPoint*, float> &_ap_distances,
float z) ;
} ;
#endif // _OWLPS_POSITIONING_MINMAX_HH_

View File

@ -5,7 +5,7 @@
#include "multilaterationmethod.hh"
/// Super-class of multilateration-based positioning algorithms
class MultilaterationAlgorithm: public PositioningAlgorithm
class MultilaterationAlgorithm: public virtual PositioningAlgorithm
{
protected:
const Request *request ;
@ -18,6 +18,7 @@ protected:
double make_constant_term(const Measurement &measurement) ;
void compute_ap_distance_circles() ;
Point3D multilaterate() ;
Point3D multilaterate_2d(float z) ;
//@}
public:
@ -40,5 +41,11 @@ inline Point3D MultilaterationAlgorithm::multilaterate()
}
inline Point3D MultilaterationAlgorithm::multilaterate_2d(float z)
{
return multilateration_method->multilaterate_2d(ap_distances, z) ;
}
#endif // _OWLPS_POSITIONING_MULTILATERATIONALGORITHM_HH_

View File

@ -19,8 +19,14 @@ public:
MultilaterationMethod(void) {}
virtual ~MultilaterationMethod(void) {}
/// Select a point in 3D space
virtual Point3D multilaterate(
const std::tr1::unordered_map<AccessPoint*, float> &ap_distances) = 0 ;
/// Select a point in 2D space, given its vertical coordinate (z)
virtual Point3D multilaterate_2d(
const std::tr1::unordered_map<AccessPoint*, float> &ap_distances,
float z) = 0 ;
} ;
#endif // _OWLPS_POSITIONING_MULTILATERATIONMETHOD_HH_

View File

@ -1,6 +1,7 @@
#include "positioning.hh"
#include "realposition.hh"
#include "fbcm.hh"
#include "frbhmbasic.hh"
#include "interlinknetworks.hh"
#include "radar.hh"
#include "configuration.hh"
@ -55,6 +56,10 @@ void Positioning::initialise_algorithms()
algorithms.push_back(new FBCM) ;
}
else if (*i == "FRBHMBasic")
//TODO: Pre-compute all per-ReferencePoint friis indexes?
algorithms.push_back(new FRBHMBasic) ;
else if (*i == "InterlinkNetworks")
algorithms.push_back(new InterlinkNetworks) ;

View File

@ -3,7 +3,7 @@
Point3D RADAR::select_point(const Request &request)
const ReferencePoint& RADAR::select_point(const Request &request)
{
return Stock::closest_reference_point(request) ;
}

View File

@ -16,7 +16,7 @@ public:
RADAR(void) {}
~RADAR(void) {}
Point3D select_point(const Request &request) ;
const ReferencePoint& select_point(const Request &request) ;
} ;
#endif // _OWLPS_POSITIONING_RADAR_HH_

View File

@ -131,11 +131,84 @@ float ReferencePoint::compute_ss_square_distance(
}
/**
* @param ap_mac The MAC address of the AccessPoint to work on.
* @returns The Friis index associated to the AccessPoint.
* @returns 0 if the AP is unknown at this ReferencePoint.
*/
float ReferencePoint::
friis_index_for_ap(const string &ap_mac) const
{
const AccessPoint &ap = Stock::get_ap(ap_mac) ;
double ap_freq = ap.get_frequency() ;
double const_term =
ap.get_antenna_gain()
- 20 * log10(4 * M_PI)
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
+ ap.get_trx_power() ;
int nb_friis_idx = 0 ;
double friis_idx_sum =
friis_indexes_for_ap(ap, const_term, nb_friis_idx) ;
if (nb_friis_idx == 0)
return 0 ;
return friis_idx_sum / nb_friis_idx ;
}
/**
* @param ap The AccessPoint to work on.
* @param const_term The "constant" part of the computation.
* @param nb_indexes (result) The number of indexes computed.
* @return The sum of all Friis indexes for the AccessPoint.
* @returns 0 if the AP is unknown at this ReferencePoint.
*/
float ReferencePoint::friis_indexes_for_ap(
const AccessPoint &ap,
const double &const_term,
int &nb_indexes) const
{
nb_indexes = 0 ;
double friis_idx_sum = 0 ;
const string &ap_mac = ap.get_mac_addr() ;
/*
* Compute an index for each Measurement in each Request in the
* ReferencePoint. The Friis index for the AP is the average of all
* these indexes (we do not compute the average in this function).
*/
for (vector<CalibrationRequest*>::const_iterator request =
requests.begin() ; request != requests.end() ; ++request)
{
const unordered_map<string, Measurement> &measurements =
(*request)->get_measurements() ;
unordered_map<string, Measurement>::const_iterator measurement =
measurements.find(ap_mac) ;
if (measurement != measurements.end())
{
float distance = this->distance(ap.get_coordinates()) ;
double ss = measurement->second.get_average_ss() ;
float mobile_gain =
(*request)->get_mobile()->get_antenna_gain() ;
friis_idx_sum +=
(const_term + mobile_gain - ss)
/ (10 * log10(distance)) ;
++nb_indexes ;
}
}
return friis_idx_sum ;
}
/* *** Operators *** */
const ReferencePoint& ReferencePoint::operator=(const ReferencePoint &source)
const ReferencePoint& ReferencePoint::
operator=(const ReferencePoint &source)
{
if (this == &source)
return *this ;

View File

@ -1,6 +1,7 @@
#ifndef _OWLPS_POSITIONING_REFERENCEPOINT_HH_
#define _OWLPS_POSITIONING_REFERENCEPOINT_HH_
class AccessPoint ;
class CalibrationRequest ;
class Request ;
class Measurement ;
@ -61,6 +62,12 @@ public:
//@{
/// Compute the distance between the ReferencePoint and a Request
float ss_square_distance(const Request &source) const ;
/// Compute the Friis index for the given AccessPoint
float friis_index_for_ap(const std::string &ap_mac) const ;
/// Compute the Friis indexes sum for the given AccessPoint
float friis_indexes_for_ap(
const AccessPoint &ap, const double &const_term,
int &nb_indexes) const ;
//@}
/** @name Operators */

View File

@ -171,34 +171,20 @@ void Stock::update_all_friis_indexes()
+ ap->second.get_trx_power() ;
/*
* Compute an index for each Measurement in each Request in each
* ReferencePoint. The Friis index for an AP is the average of all
* these indexes.
* 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)
{
for (vector<CalibrationRequest*>::const_iterator request =
rp->get_requests().begin() ;
request != rp->get_requests().end() ; ++request)
int nb_idx = 0 ;
float ap_friis_idx_sum =
rp->friis_indexes_for_ap(ap->second, const_term, nb_idx) ;
if (nb_idx != 0)
{
const unordered_map<string, Measurement> &measurements =
(*request)->get_measurements() ;
unordered_map<string, Measurement>::const_iterator
measurement = measurements.find(ap_mac) ;
if (measurement != measurements.end())
{
double ss = measurement->second.get_average_ss() ;
float distance =
rp->distance(ap->second.get_coordinates()) ;
float mobile_gain =
(*request)->get_mobile()->get_antenna_gain() ;
friis_idx_sum +=
(const_term + mobile_gain - ss)
/ (10 * log10(distance)) ;
++nb_friis_idx ;
}
friis_idx_sum += ap_friis_idx_sum ;
nb_friis_idx += nb_idx ;
}
}

View File

@ -172,7 +172,7 @@ void UserInterface::fill_positioning_options()
("positioning.algorithm,a", po::value< vector<string> >()->composing(),
"Algorithms used to compute positions. You can specify \
this option more than once (but at least once). Allowed: Real, FBCM, \
InterlinkNetworks, RADAR.")
FRBHMBasic, InterlinkNetworks, RADAR.")
;
file_options->add(options) ;

View File

@ -0,0 +1,24 @@
#include <cxxtest/TestSuite.h>
#include "frbhmbasic.hh"
class FRBHMBasic_test: public CxxTest::TestSuite
{
public:
void test_compute(void)
{
PositioningAlgorithm *algo = new FRBHMBasic() ;
/*
* TODO: implement the test.
* I was told to accelerate the development, so I leave unneeded unit
* tests for later. This tests *is* actually needed, but I did some
* result comparison between the old version of OWLPS Positioning and
* the current one, and, hm, let's say it's OK for now
*/
delete algo ;
}
} ;