[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:
parent
e12db08b0d
commit
c731bf578f
|
@ -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
|
||||
|
|
|
@ -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 ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
|
|
|
@ -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() ;
|
||||
}
|
||||
|
|
|
@ -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) {}
|
||||
|
|
|
@ -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()) ;
|
||||
}
|
|
@ -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_
|
|
@ -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) ;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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) ;
|
||||
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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 ;
|
||||
}
|
||||
|
||||
} ;
|
Loading…
Reference in New Issue