[Positioner] Add class Autocalibration
The new class Autocalibration contains the code from the former huge function Stock::generate_reference_point(). It is refactored a bit, but still needs work. The function Stock::generate_reference_points() stays in the Stock class for now.
This commit is contained in:
parent
d479f9d080
commit
7a631e3962
|
@ -74,6 +74,7 @@ SOURCE_TARGET = $(SRC_DIR)/$(TARGET).cc
|
||||||
|
|
||||||
OBJ_LIST = \
|
OBJ_LIST = \
|
||||||
posutil.o \
|
posutil.o \
|
||||||
|
autocalibration.o \
|
||||||
stock.o \
|
stock.o \
|
||||||
timestamp.o \
|
timestamp.o \
|
||||||
direction.o \
|
direction.o \
|
||||||
|
@ -165,6 +166,10 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc $(SRC_DIR)/%.hh
|
||||||
$(STRIP) $@
|
$(STRIP) $@
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
|
$(OBJ_DIR)/autocalibration.o: \
|
||||||
|
$(OBJ_DIR)/stock.o \
|
||||||
|
$(OBJ_DIR)/configuration.o \
|
||||||
|
$(OBJ_DIR)/posexcept.o
|
||||||
$(OBJ_DIR)/point3d.o: \
|
$(OBJ_DIR)/point3d.o: \
|
||||||
$(OBJ_DIR)/posutil.o \
|
$(OBJ_DIR)/posutil.o \
|
||||||
$(OBJ_DIR)/posexcept.o
|
$(OBJ_DIR)/posexcept.o
|
||||||
|
|
|
@ -0,0 +1,251 @@
|
||||||
|
#include "autocalibration.hh"
|
||||||
|
|
||||||
|
#include "accesspoint.hh"
|
||||||
|
#include "stock.hh"
|
||||||
|
#include "configuration.hh"
|
||||||
|
#include "posexcept.hh"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
using namespace std ;
|
||||||
|
using std::tr1::unordered_map ;
|
||||||
|
|
||||||
|
|
||||||
|
/* *** Static attribute definitions *** */
|
||||||
|
|
||||||
|
uint32_t Autocalibration::nb_virtual_mobiles = 0 ;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reference point P we want to generate will end-up containing
|
||||||
|
* as many calibration requests as the total number of APs.
|
||||||
|
* For each of these requests, we consider a transmitter TRX (which is
|
||||||
|
* a virtual mobile located in P) and a receiver RX (the current AP).
|
||||||
|
* To generate the signal strength (SS) received by RX from TRX,
|
||||||
|
* we first select two reference APs REF1 and REF2. Then, we average
|
||||||
|
* the real measurements REF1->RX and REF2->RX, weighting in function
|
||||||
|
* of the angles REF-RX-TRX and the distance from RX to TRX to compute
|
||||||
|
* the SS.
|
||||||
|
* Hope this is clear enough…
|
||||||
|
*/
|
||||||
|
void Autocalibration::generate_reference_point()
|
||||||
|
{
|
||||||
|
// If the point is the coordinates of an existing AP, we don't
|
||||||
|
// need to generate it
|
||||||
|
if (Stock::is_ap_coordinate(point))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
/* Get/create the reference point */
|
||||||
|
const ReferencePoint
|
||||||
|
¤t_rp = Stock::find_create_reference_point(point) ;
|
||||||
|
|
||||||
|
/* Create the timestamp */
|
||||||
|
Timestamp time_sent ;
|
||||||
|
time_sent.now() ;
|
||||||
|
|
||||||
|
/* Prepare the virtual mobile */
|
||||||
|
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
|
||||||
|
// The gain and trx power of the mobile will be the average of
|
||||||
|
// those of all the known APs (could be better, probably)
|
||||||
|
vmob_gain = 0 ;
|
||||||
|
vmob_pow = 0 ;
|
||||||
|
|
||||||
|
/* Generate a SS per AP */
|
||||||
|
for (unordered_map<string, AccessPoint>::const_iterator
|
||||||
|
rx = Stock::aps.begin() ; rx != Stock::aps.end() ; ++rx)
|
||||||
|
generate_ss() ;
|
||||||
|
|
||||||
|
/* Create the virtual mobile */
|
||||||
|
Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ;
|
||||||
|
const Mobile &mobile = Stock::find_create_mobile(vmob) ;
|
||||||
|
|
||||||
|
/* Create the calibration request */
|
||||||
|
CalibrationRequest cr(OWL_REQUEST_GENERATED) ;
|
||||||
|
cr.set_time_sent(time_sent) ;
|
||||||
|
cr.set_mobile(&mobile) ;
|
||||||
|
cr.set_measurements(measurements) ;
|
||||||
|
cr.set_reference_point(¤t_rp) ;
|
||||||
|
|
||||||
|
Stock::store_calibration_request(cr) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Autocalibration::generate_ss()
|
||||||
|
{
|
||||||
|
/* Update the mobile's attributes */
|
||||||
|
vmob_gain += rx->second.get_antenna_gain() / Stock::aps.size() ;
|
||||||
|
vmob_pow += rx->second.get_trx_power() / Stock::aps.size() ;
|
||||||
|
|
||||||
|
/* Skip the AP if it is not at the good level (floor) */
|
||||||
|
const Point3D &rx_coord = rx->second.get_coordinates() ;
|
||||||
|
if (rx_coord.get_z() != point.get_z())
|
||||||
|
return ;
|
||||||
|
|
||||||
|
/* Choose the 2 nearest APs in angle */
|
||||||
|
choose_reference_aps() ;
|
||||||
|
if (sorted_angles.size() < 2)
|
||||||
|
throw autocalibration_error("Not enough APs in coverage!") ;
|
||||||
|
|
||||||
|
/* Compute the angle weight of the 2 reference APs */
|
||||||
|
weight_aps() ;
|
||||||
|
|
||||||
|
/* Compute the SS that would be received from a mobile at a
|
||||||
|
* distance of RX-P, in the direction of each reference AP */
|
||||||
|
// Distance RX-P
|
||||||
|
float point_dst = rx_coord.distance(point) ;
|
||||||
|
// Constant term
|
||||||
|
double common_ss = rx->second.friis_constant_term() ;
|
||||||
|
|
||||||
|
const string &rx_mac = rx->second.get_mac_addr() ;
|
||||||
|
const ReferencePoint
|
||||||
|
&ref1_rp = Stock::get_reference_point(ref1->get_coordinates()),
|
||||||
|
&ref2_rp = Stock::get_reference_point(ref2->get_coordinates()) ;
|
||||||
|
|
||||||
|
if (Configuration::
|
||||||
|
bool_value("positioning.generate-single-packet-reference-points"))
|
||||||
|
{
|
||||||
|
/* Friis indexes for REF1 & REF2 */
|
||||||
|
float ref1_friis_idx = ref1_rp.friis_index_for_ap(rx_mac) ;
|
||||||
|
float ref2_friis_idx = ref2_rp.friis_index_for_ap(rx_mac) ;
|
||||||
|
|
||||||
|
/* SS for REF1 & REF2 */
|
||||||
|
double ref1_ss =
|
||||||
|
common_ss +
|
||||||
|
ref1->get_trx_power() +
|
||||||
|
ref1->get_antenna_gain() -
|
||||||
|
10 * ref1_friis_idx * log10(point_dst) ;
|
||||||
|
double ref2_ss =
|
||||||
|
common_ss +
|
||||||
|
ref2->get_trx_power() +
|
||||||
|
ref2->get_antenna_gain() -
|
||||||
|
10 * ref2_friis_idx * log10(point_dst) ;
|
||||||
|
|
||||||
|
/* Compute the consolidated SS */
|
||||||
|
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
||||||
|
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
||||||
|
double rx_ss = ref1_ss + ref2_ss ;
|
||||||
|
|
||||||
|
/* Create the measurement, add it to the list */
|
||||||
|
Measurement m(&rx->second) ;
|
||||||
|
m.add_ss(1, rx_ss) ;
|
||||||
|
measurements[rx_mac] = m ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const vector<CalibrationRequest*> &ref1_cr =
|
||||||
|
ref1_rp.get_requests() ;
|
||||||
|
const Measurement *rx_measurement = NULL ;
|
||||||
|
vector<CalibrationRequest*>::const_iterator cr ;
|
||||||
|
|
||||||
|
// Search for the first measurement made by RX in ref1_rp
|
||||||
|
for (cr = ref1_cr.begin() ;
|
||||||
|
! rx_measurement && cr != ref1_cr.end() ; ++cr)
|
||||||
|
rx_measurement = (*cr)->get_measurement(rx_mac) ;
|
||||||
|
|
||||||
|
// The selected reference APs are in coverage of RX, therefore
|
||||||
|
// we should always find a measurement of RX in ref1_rp
|
||||||
|
assert(rx_measurement) ;
|
||||||
|
|
||||||
|
for (pkt_id_t pkt_id = 1 ; pkt_id < (*cr)->get_nb_packets() ;
|
||||||
|
++pkt_id)
|
||||||
|
{
|
||||||
|
/* Friis indexes for REF1 & REF2 */
|
||||||
|
float ref1_friis_idx =
|
||||||
|
ref1_rp.friis_index_for_ap(rx->second.get_mac_addr(),
|
||||||
|
pkt_id) ;
|
||||||
|
if (ref1_friis_idx == 0)
|
||||||
|
continue ; // The packet pkt_id does not exist in ref1_rp
|
||||||
|
float ref2_friis_idx =
|
||||||
|
ref2_rp.friis_index_for_ap(rx->second.get_mac_addr(),
|
||||||
|
pkt_id) ;
|
||||||
|
if (ref2_friis_idx == 0)
|
||||||
|
continue ; // The packet pkt_id does not exist in ref2_rp
|
||||||
|
|
||||||
|
/* SS for REF1 & REF2 */
|
||||||
|
double ref1_ss =
|
||||||
|
common_ss +
|
||||||
|
ref1->get_trx_power() +
|
||||||
|
ref1->get_antenna_gain() -
|
||||||
|
10 * ref1_friis_idx * log10(point_dst) ;
|
||||||
|
double ref2_ss =
|
||||||
|
common_ss +
|
||||||
|
ref2->get_trx_power() +
|
||||||
|
ref2->get_antenna_gain() -
|
||||||
|
10 * ref2_friis_idx * log10(point_dst) ;
|
||||||
|
|
||||||
|
/* Compute the consolidated SS */
|
||||||
|
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
||||||
|
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
||||||
|
double rx_ss = ref1_ss + ref2_ss ;
|
||||||
|
|
||||||
|
/* Create the measurement, add it to the list */
|
||||||
|
Measurement m(&rx->second) ;
|
||||||
|
m.add_ss(pkt_id, rx_ss) ;
|
||||||
|
measurements[rx_mac] = m ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Autocalibration::choose_reference_aps()
|
||||||
|
{
|
||||||
|
const Point3D &rx_coord = rx->second.get_coordinates() ;
|
||||||
|
|
||||||
|
for (unordered_map<string, AccessPoint>::const_iterator
|
||||||
|
ref = Stock::aps.begin() ; ref != Stock::aps.end() ; ++ref)
|
||||||
|
{
|
||||||
|
if (ref == rx)
|
||||||
|
continue ;
|
||||||
|
|
||||||
|
// Skip the AP if it is not at the same level (floor) than the
|
||||||
|
// receiver AP:
|
||||||
|
const Point3D &ref_coord = ref->second.get_coordinates() ;
|
||||||
|
if (ref_coord.get_z() != rx_coord.get_z())
|
||||||
|
continue ;
|
||||||
|
|
||||||
|
// Skip the AP if it is not in coverage with the receiver AP:
|
||||||
|
float coverage =
|
||||||
|
rx->second.received_calibration_from_ap(ref->second) ;
|
||||||
|
if (coverage < 1) // Less than 1% coverage is ridiculous!
|
||||||
|
continue ;
|
||||||
|
|
||||||
|
double angle = rx_coord.angle_2d(point, ref_coord) ;
|
||||||
|
double weight = angle / coverage ;
|
||||||
|
pair<double,
|
||||||
|
unordered_map<string, AccessPoint>::const_iterator>
|
||||||
|
angle_ap(angle, ref) ;
|
||||||
|
pair<double, pair<double,
|
||||||
|
unordered_map<string, AccessPoint>::const_iterator> >
|
||||||
|
weight_angle_ap(weight, angle_ap) ;
|
||||||
|
sorted_angles.insert(weight_angle_ap) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Autocalibration::weight_aps()
|
||||||
|
{
|
||||||
|
map<double, pair<double,
|
||||||
|
unordered_map<string, AccessPoint>::const_iterator> >
|
||||||
|
::const_iterator s = sorted_angles.begin() ;
|
||||||
|
// Angle REF1-RX-P
|
||||||
|
double ref1_angle = s->second.first ;
|
||||||
|
ref1 = &s->second.second->second ;
|
||||||
|
++s ;
|
||||||
|
ref2 = &s->second.second->second ;
|
||||||
|
|
||||||
|
// Angle REF1-RX-REF2
|
||||||
|
const Point3D &rx_coord = rx->second.get_coordinates() ;
|
||||||
|
const Point3D &ref1_coord = ref1->get_coordinates() ;
|
||||||
|
const Point3D &ref2_coord = ref2->get_coordinates() ;
|
||||||
|
double reference_angle = rx_coord.angle_2d(ref1_coord, ref2_coord) ;
|
||||||
|
if (reference_angle == 0)
|
||||||
|
ref1_percent = ref2_percent = 50 ;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ref1_percent = ref1_angle * 100 / reference_angle ;
|
||||||
|
if (ref1_percent > 100)
|
||||||
|
ref1_percent = 100 ;
|
||||||
|
ref2_percent = 100 - ref1_percent ;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Owl Positioning System (OwlPS).
|
||||||
|
* OwlPS is a project of the University of Franche-Comté
|
||||||
|
* (Université de Franche-Comté), France.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _OWLPS_POSITIONING_AUTOCALIBRATION_HH_
|
||||||
|
#define _OWLPS_POSITIONING_AUTOCALIBRATION_HH_
|
||||||
|
|
||||||
|
class AccessPoint ;
|
||||||
|
class Point3D ;
|
||||||
|
class Measurement ;
|
||||||
|
|
||||||
|
#include <boost/tr1/unordered_map.hpp>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class Autocalibration contains the code used to generate single
|
||||||
|
* reference points from the autocalibration measurements.
|
||||||
|
*/
|
||||||
|
class Autocalibration
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/// Current AP to generate a SS for
|
||||||
|
std::tr1::unordered_map<std::string, AccessPoint>::const_iterator rx ;
|
||||||
|
/// Selected transmitter APs
|
||||||
|
const AccessPoint *ref1, *ref2 ;
|
||||||
|
/// Weights of the selected transmitter APs
|
||||||
|
double ref1_percent, ref2_percent ;
|
||||||
|
/// Angles of the transmitter APs
|
||||||
|
std::multimap<double,
|
||||||
|
std::pair<double,
|
||||||
|
std::tr1::unordered_map<
|
||||||
|
std::string, AccessPoint>::const_iterator> >
|
||||||
|
sorted_angles ;
|
||||||
|
/// Characteristics of the virtual mobile
|
||||||
|
double vmob_gain, vmob_pow ;
|
||||||
|
/// Generated measurements' list
|
||||||
|
std::tr1::unordered_map<std::string, Measurement> measurements ;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Number of generated "virtual" mobiles
|
||||||
|
static uint32_t nb_virtual_mobiles ;
|
||||||
|
|
||||||
|
/// The coordinates of the reference point to generate
|
||||||
|
const Point3D &point ;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Autocalibration(const Point3D &_point): point(_point) {}
|
||||||
|
|
||||||
|
/// Generates a single reference point
|
||||||
|
void generate_reference_point(void) ;
|
||||||
|
/// Generates the SSs for all the APs
|
||||||
|
void generate_ss(void) ;
|
||||||
|
/// Chooses the reference APs for a receiver AP
|
||||||
|
void choose_reference_aps(void) ;
|
||||||
|
/// Weihgts the selected APs according to their angles
|
||||||
|
void weight_aps(void) ;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#endif // _OWLPS_POSITIONING_AUTOCALIBRATION_HH_
|
|
@ -26,8 +26,6 @@ unordered_map<Point3D, Waypoint> Stock::waypoints ;
|
||||||
|
|
||||||
unordered_map<string, Mobile> Stock::mobiles ;
|
unordered_map<string, Mobile> Stock::mobiles ;
|
||||||
|
|
||||||
uint32_t Stock::nb_virtual_mobiles = 0 ;
|
|
||||||
|
|
||||||
unordered_map<string, AccessPoint> Stock::aps ;
|
unordered_map<string, AccessPoint> Stock::aps ;
|
||||||
|
|
||||||
unordered_set<ReferencePoint,
|
unordered_set<ReferencePoint,
|
||||||
|
@ -464,233 +462,17 @@ void Stock::regenerate_reference_points()
|
||||||
for (float z = start.get_z() ; z <= stop.get_z() ; z += step_z)
|
for (float z = start.get_z() ; z <= stop.get_z() ; z += step_z)
|
||||||
{
|
{
|
||||||
Point3D current_point(x,y,z) ;
|
Point3D current_point(x,y,z) ;
|
||||||
generate_reference_point(current_point) ;
|
Autocalibration ac(current_point) ;
|
||||||
}
|
try
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reference point P we want to generate will end-up containing
|
|
||||||
* as many calibration requests as the total number of APs.
|
|
||||||
* For each of these requests, we consider a transmitter TRX (which is
|
|
||||||
* a virtual mobile located in P) and a receiver RX (the current AP).
|
|
||||||
* To generate the signal strength (SS) received by RX from TRX,
|
|
||||||
* we first select two reference APs REF1 and REF2. Then, we average
|
|
||||||
* the real measurements REF1->RX and REF2->RX, weighting in function
|
|
||||||
* of the angles REF-RX-TRX and the distance from RX to TRX to compute
|
|
||||||
* the SS.
|
|
||||||
* Hope this is clear enough…
|
|
||||||
*/
|
|
||||||
void Stock::generate_reference_point(const Point3D &point)
|
|
||||||
{
|
|
||||||
// If the point is the coordinates of an existing AP, we don't
|
|
||||||
// need to generate it
|
|
||||||
if (is_ap_coordinate(point))
|
|
||||||
return ;
|
|
||||||
|
|
||||||
/* Get/create the reference point */
|
|
||||||
const ReferencePoint ¤t_rp = find_create_reference_point(point) ;
|
|
||||||
|
|
||||||
/* Create the timestamp */
|
|
||||||
Timestamp time_sent ;
|
|
||||||
time_sent.now() ;
|
|
||||||
|
|
||||||
/* Create the measurement list */
|
|
||||||
unordered_map<string, Measurement> measurements ;
|
|
||||||
|
|
||||||
/* Prepare the virtual mobile */
|
|
||||||
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
|
|
||||||
// The gain and trx power of the mobile will be the average of
|
|
||||||
// those of all the known APs (could be better, probably)
|
|
||||||
double vmob_gain = 0 ;
|
|
||||||
double vmob_pow = 0 ;
|
|
||||||
|
|
||||||
for (unordered_map<string, AccessPoint>::const_iterator
|
|
||||||
rx = aps.begin() ; rx != aps.end() ; ++rx)
|
|
||||||
{
|
|
||||||
/* Update the mobile's attributes */
|
|
||||||
vmob_gain += rx->second.get_antenna_gain() / aps.size() ;
|
|
||||||
vmob_pow += rx->second.get_trx_power() / aps.size() ;
|
|
||||||
|
|
||||||
/* Skip the AP if it is not at the good level (floor) */
|
|
||||||
const Point3D &rx_coord = rx->second.get_coordinates() ;
|
|
||||||
if (rx_coord.get_z() != point.get_z())
|
|
||||||
continue ;
|
|
||||||
|
|
||||||
/* Choose the 2 nearest APs in angle */
|
|
||||||
multimap<double, pair<double,
|
|
||||||
unordered_map<string, AccessPoint>::const_iterator> >
|
|
||||||
sorted_angles ;
|
|
||||||
for (unordered_map<string, AccessPoint>::const_iterator
|
|
||||||
ref = aps.begin() ; ref != aps.end() ; ++ref)
|
|
||||||
{
|
|
||||||
if (ref == rx)
|
|
||||||
continue ;
|
|
||||||
|
|
||||||
// Skip the AP if it is not at the same level (floor) than the
|
|
||||||
// receiver AP:
|
|
||||||
const Point3D &ref_coord = ref->second.get_coordinates() ;
|
|
||||||
if (ref_coord.get_z() != rx_coord.get_z())
|
|
||||||
continue ;
|
|
||||||
|
|
||||||
// Skip the AP if it is not in coverage with the receiver AP:
|
|
||||||
float coverage =
|
|
||||||
rx->second.received_calibration_from_ap(ref->second) ;
|
|
||||||
if (coverage < 1) // Less than 1% coverage is ridiculous!
|
|
||||||
continue ;
|
|
||||||
|
|
||||||
double angle = rx_coord.angle_2d(point, ref_coord) ;
|
|
||||||
double weight = angle / coverage ;
|
|
||||||
pair<double,
|
|
||||||
unordered_map<string, AccessPoint>::const_iterator>
|
|
||||||
angle_ap(angle, ref) ;
|
|
||||||
pair<double, pair<double,
|
|
||||||
unordered_map<string, AccessPoint>::const_iterator> >
|
|
||||||
weight_angle_ap(weight, angle_ap) ;
|
|
||||||
sorted_angles.insert(weight_angle_ap) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sorted_angles.size() < 2)
|
|
||||||
{
|
|
||||||
if (Configuration::is_configured("verbose"))
|
|
||||||
cerr << "Can't generate reference point, not enough APs"
|
|
||||||
<< " in coverage!\n" ;
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the angle weight of the 2 reference APs */
|
|
||||||
map<double, pair<double,
|
|
||||||
unordered_map<string, AccessPoint>::const_iterator> >
|
|
||||||
::const_iterator s = sorted_angles.begin() ;
|
|
||||||
// Angle REF1-RX-P
|
|
||||||
double ref1_angle = s->second.first ;
|
|
||||||
const AccessPoint &ref1 = s->second.second->second ;
|
|
||||||
++s ;
|
|
||||||
const AccessPoint &ref2 = s->second.second->second ;
|
|
||||||
|
|
||||||
// Angle REF1-RX-REF2
|
|
||||||
const Point3D &ref1_coord = ref1.get_coordinates() ;
|
|
||||||
const Point3D &ref2_coord = ref2.get_coordinates() ;
|
|
||||||
double reference_angle = rx_coord.angle_2d(ref1_coord, ref2_coord) ;
|
|
||||||
double ref1_percent, ref2_percent ;
|
|
||||||
if (reference_angle == 0)
|
|
||||||
ref1_percent = ref2_percent = 50 ;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ref1_percent = ref1_angle * 100 / reference_angle ;
|
|
||||||
if (ref1_percent > 100)
|
|
||||||
ref1_percent = 100 ;
|
|
||||||
ref2_percent = 100 - ref1_percent ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the SS that would be received from a mobile at a
|
|
||||||
* distance of RX-P, in the direction of each reference AP */
|
|
||||||
// Distance RX-P
|
|
||||||
float point_dst = rx_coord.distance(point) ;
|
|
||||||
// Constant term
|
|
||||||
double common_ss = rx->second.friis_constant_term() ;
|
|
||||||
|
|
||||||
const string &rx_mac = rx->second.get_mac_addr() ;
|
|
||||||
const ReferencePoint &ref1_rp = get_reference_point(ref1_coord) ;
|
|
||||||
const ReferencePoint &ref2_rp = get_reference_point(ref2_coord) ;
|
|
||||||
|
|
||||||
if (Configuration::
|
|
||||||
bool_value("positioning.generate-single-packet-reference-points"))
|
|
||||||
{
|
|
||||||
/* Friis indexes for REF1 & REF2 */
|
|
||||||
float ref1_friis_idx = ref1_rp.friis_index_for_ap(rx_mac) ;
|
|
||||||
float ref2_friis_idx = ref2_rp.friis_index_for_ap(rx_mac) ;
|
|
||||||
|
|
||||||
/* SS for REF1 & REF2 */
|
|
||||||
double ref1_ss =
|
|
||||||
common_ss +
|
|
||||||
ref1.get_trx_power() +
|
|
||||||
ref1.get_antenna_gain() -
|
|
||||||
10 * ref1_friis_idx * log10(point_dst) ;
|
|
||||||
double ref2_ss =
|
|
||||||
common_ss +
|
|
||||||
ref2.get_trx_power() +
|
|
||||||
ref2.get_antenna_gain() -
|
|
||||||
10 * ref2_friis_idx * log10(point_dst) ;
|
|
||||||
|
|
||||||
/* Compute the consolidated SS */
|
|
||||||
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
|
||||||
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
|
||||||
double rx_ss = ref1_ss + ref2_ss ;
|
|
||||||
|
|
||||||
/* Create the measurement, add it to the list */
|
|
||||||
Measurement m(&rx->second) ;
|
|
||||||
m.add_ss(1, rx_ss) ;
|
|
||||||
measurements[rx_mac] = m ;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const vector<CalibrationRequest*> &ref1_cr =
|
|
||||||
ref1_rp.get_requests() ;
|
|
||||||
const Measurement *rx_measurement = NULL ;
|
|
||||||
vector<CalibrationRequest*>::const_iterator cr ;
|
|
||||||
|
|
||||||
// Search for the first measurement made by RX in ref1_rp
|
|
||||||
for (cr = ref1_cr.begin() ;
|
|
||||||
! rx_measurement && cr != ref1_cr.end() ; ++cr)
|
|
||||||
rx_measurement = (*cr)->get_measurement(rx_mac) ;
|
|
||||||
|
|
||||||
// The selected reference APs are in coverage of RX, therefore
|
|
||||||
// we should always find a measurement of RX in ref1_rp
|
|
||||||
assert(rx_measurement) ;
|
|
||||||
|
|
||||||
for (pkt_id_t pkt_id = 1 ; pkt_id < (*cr)->get_nb_packets() ;
|
|
||||||
++pkt_id)
|
|
||||||
{
|
{
|
||||||
/* Friis indexes for REF1 & REF2 */
|
ac.generate_reference_point() ;
|
||||||
float ref1_friis_idx =
|
}
|
||||||
ref1_rp.friis_index_for_ap(rx->second.get_mac_addr(),
|
catch (autocalibration_error &e)
|
||||||
pkt_id) ;
|
{
|
||||||
if (ref1_friis_idx == 0)
|
if (Configuration::is_configured("verbose"))
|
||||||
continue ; // The packet pkt_id does not exist in ref1_rp
|
cerr << e.what() << '\n' ;
|
||||||
float ref2_friis_idx =
|
|
||||||
ref2_rp.friis_index_for_ap(rx->second.get_mac_addr(),
|
|
||||||
pkt_id) ;
|
|
||||||
if (ref2_friis_idx == 0)
|
|
||||||
continue ; // The packet pkt_id does not exist in ref2_rp
|
|
||||||
|
|
||||||
/* SS for REF1 & REF2 */
|
|
||||||
double ref1_ss =
|
|
||||||
common_ss +
|
|
||||||
ref1.get_trx_power() +
|
|
||||||
ref1.get_antenna_gain() -
|
|
||||||
10 * ref1_friis_idx * log10(point_dst) ;
|
|
||||||
double ref2_ss =
|
|
||||||
common_ss +
|
|
||||||
ref2.get_trx_power() +
|
|
||||||
ref2.get_antenna_gain() -
|
|
||||||
10 * ref2_friis_idx * log10(point_dst) ;
|
|
||||||
|
|
||||||
/* Compute the consolidated SS */
|
|
||||||
ref1_ss = ref1_ss * ref1_percent / 100 ;
|
|
||||||
ref2_ss = ref2_ss * ref2_percent / 100 ;
|
|
||||||
double rx_ss = ref1_ss + ref2_ss ;
|
|
||||||
|
|
||||||
/* Create the measurement, add it to the list */
|
|
||||||
Measurement m(&rx->second) ;
|
|
||||||
m.add_ss(pkt_id, rx_ss) ;
|
|
||||||
measurements[rx_mac] = m ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Create the virtual mobile */
|
|
||||||
Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ;
|
|
||||||
const Mobile &mobile = find_create_mobile(vmob) ;
|
|
||||||
|
|
||||||
/* Create the calibration request */
|
|
||||||
CalibrationRequest cr(OWL_REQUEST_GENERATED) ;
|
|
||||||
cr.set_time_sent(time_sent) ;
|
|
||||||
cr.set_mobile(&mobile) ;
|
|
||||||
cr.set_measurements(measurements) ;
|
|
||||||
cr.set_reference_point(¤t_rp) ;
|
|
||||||
|
|
||||||
store_calibration_request(cr) ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef _OWLPS_POSITIONING_STOCK_HH_
|
#ifndef _OWLPS_POSITIONING_STOCK_HH_
|
||||||
#define _OWLPS_POSITIONING_STOCK_HH_
|
#define _OWLPS_POSITIONING_STOCK_HH_
|
||||||
|
|
||||||
|
#include "autocalibration.hh"
|
||||||
#include "building.hh"
|
#include "building.hh"
|
||||||
#include "waypoint.hh"
|
#include "waypoint.hh"
|
||||||
#include "mobile.hh"
|
#include "mobile.hh"
|
||||||
|
@ -21,6 +22,8 @@
|
||||||
/// Storage class
|
/// Storage class
|
||||||
class Stock
|
class Stock
|
||||||
{
|
{
|
||||||
|
friend class Autocalibration ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// List of known Building
|
/// List of known Building
|
||||||
/** The string key of the map is the Building name. */
|
/** The string key of the map is the Building name. */
|
||||||
|
@ -33,9 +36,6 @@ private:
|
||||||
/** The string key of the map is the Mobile MAC address. */
|
/** The string key of the map is the Mobile MAC address. */
|
||||||
static std::tr1::unordered_map<std::string, Mobile> mobiles ;
|
static std::tr1::unordered_map<std::string, Mobile> mobiles ;
|
||||||
|
|
||||||
/// Number of generated "virtual" mobiles
|
|
||||||
static uint32_t nb_virtual_mobiles ;
|
|
||||||
|
|
||||||
/// List of known AccessPoint
|
/// List of known AccessPoint
|
||||||
/** The string key of the map is the AccessPoint MAC address. */
|
/** The string key of the map is the AccessPoint MAC address. */
|
||||||
static std::tr1::unordered_map<std::string, AccessPoint> aps ;
|
static std::tr1::unordered_map<std::string, AccessPoint> aps ;
|
||||||
|
@ -48,12 +48,6 @@ private:
|
||||||
/// List of known CalibrationRequest
|
/// List of known CalibrationRequest
|
||||||
static std::tr1::unordered_set<CalibrationRequest> calibration_requests ;
|
static std::tr1::unordered_set<CalibrationRequest> calibration_requests ;
|
||||||
|
|
||||||
/** @name ReferencePoint operations */
|
|
||||||
//@{
|
|
||||||
/// Generates a single reference point
|
|
||||||
static void generate_reference_point(const Point3D &point) ;
|
|
||||||
//@}
|
|
||||||
|
|
||||||
/** @name CalibrationRequest operations */
|
/** @name CalibrationRequest operations */
|
||||||
//@{
|
//@{
|
||||||
/// Delete calibration requests that do not come from the APs
|
/// Delete calibration requests that do not come from the APs
|
||||||
|
|
Loading…
Reference in New Issue