From 2ac9cc2c1d5431b7acc3f5ececc8598b7c4ab108 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 8 Jul 2013 13:19:04 -0400 Subject: [PATCH] [Positioner] Add AutocalibrationMesh (refactored) Refactor pieces of Autocalibration into the new class AutocalibrationMesh, in order to allow the addition of new autocalibration sub-classes. --- owlps-positioner/CMakeLists.txt | 1 + owlps-positioner/autocalibration.cc | 279 ++-------------------- owlps-positioner/autocalibration.hh | 79 ++----- owlps-positioner/autocalibrationmesh.cc | 297 ++++++++++++++++++++++++ owlps-positioner/autocalibrationmesh.hh | 83 +++++++ owlps-positioner/stock.cc | 3 +- owlps-positioner/stock.hh | 2 +- 7 files changed, 420 insertions(+), 324 deletions(-) create mode 100644 owlps-positioner/autocalibrationmesh.cc create mode 100644 owlps-positioner/autocalibrationmesh.hh diff --git a/owlps-positioner/CMakeLists.txt b/owlps-positioner/CMakeLists.txt index ac426c3..5ff914e 100644 --- a/owlps-positioner/CMakeLists.txt +++ b/owlps-positioner/CMakeLists.txt @@ -44,6 +44,7 @@ set(OWLPS_POSITIONER_CLASSES_SRC_FILES capturepointsreadercsv.cc area.cc autocalibration.cc + autocalibrationmesh.cc building.cc calibrationrequest.cc cartographyalgorithm.cc diff --git a/owlps-positioner/autocalibration.cc b/owlps-positioner/autocalibration.cc index 2180336..4bb6596 100644 --- a/owlps-positioner/autocalibration.cc +++ b/owlps-positioner/autocalibration.cc @@ -14,15 +14,12 @@ #include "autocalibration.hh" -#include "capturepoint.hh" #include "stock.hh" #include "configuration.hh" #include "posexcept.hh" -#include #include #include -#include using namespace std ; @@ -36,8 +33,9 @@ uint32_t Autocalibration::nb_virtual_mobiles = 0 ; /* *** Operations *** */ + /** - * The reference point P we want to generate will end-up containing + * The reference point P we want to generate will end up containing * as many calibration requests as the total number of CPs. * For each of these requests, we consider a transmitter TRX (which is * a virtual mobile located in P) and a receiver RX (the current CP). @@ -68,7 +66,10 @@ void Autocalibration::generate_reference_point() /* Generate the SS(s) for each CP */ for (rx = Stock::cps.begin() ; rx != Stock::cps.end() ; ++rx) - generate_ss() ; + { + if (init_ss_generation()) + generate_ss() ; + } assert(! measurements.empty()) ; /* Create the virtual mobile */ @@ -86,7 +87,11 @@ void Autocalibration::generate_reference_point() } -void Autocalibration::generate_ss() +/** + * @returns `true` if the SS can be generated. + * @returns `false` in case of error. + */ +bool Autocalibration::init_ss_generation() { /* Update the mobile's attributes */ vmob_gain += rx->second.get_antenna_gain() / Stock::cps.size() ; @@ -96,153 +101,16 @@ void Autocalibration::generate_ss() * to generate */ const Point3D &rx_coord = rx->second.get_coordinates() ; if (rx_coord.get_z() != point.get_z()) - return ; + return false ; - /* Compute the origin angle P-RX-O */ - Point3D origin(rx_coord) ; - origin.set_x(rx_coord.get_x() + 10) ; - origin_angle = rx_coord.angle_2d(point, origin) ; - if (point.get_y() > rx_coord.get_y()) - origin_angle = -origin_angle ; - - /* Choose the nearest CP(s) in angle */ - sort_reference_cps() ; - // We need at least one reference CP: - if (sorted_negative_angles.empty() && sorted_positive_angles.empty()) - throw autocalibration_error("Not enough CPs in coverage!") ; - - /* Compute the angle weight of the reference CPs */ - weight_cps() ; - - /* Compute the SS that would be received from a mobile at a - * distance of RX-P, in the direction of each reference CP */ - compute_ss() ; + return true ; } /** - * The reference (transmitter) CPs are first filtered (floor, coverage), - * then sorted according to their angles with RX and P. + * This function is a simple wrapper around compute_single_packet_ss() + * and compute_multi_packet_ss(), depending on the configuration. */ -void Autocalibration::sort_reference_cps() -{ - const Point3D &rx_coord = rx->second.get_coordinates() ; - - sorted_negative_angles.clear() ; - sorted_positive_angles.clear() ; - - for (unordered_map::const_iterator - ref = Stock::cps.begin() ; ref != Stock::cps.end() ; ++ref) - { - if (ref == rx) - continue ; - - /* Skip the CP if it is not at the same floor than the - * receiver CP */ - const Point3D &ref_coord = ref->second.get_coordinates() ; - if (ref_coord.get_z() != rx_coord.get_z()) - continue ; - - /* Skip the CP if it is not in coverage with the receiver CP */ - float coverage = - rx->second.received_calibration_from_cp(ref->second) ; - if (coverage < 1) // Less than 1% coverage is ridiculous! - continue ; - - /* Angle P-RX-REF */ - double angle = rx_coord.angle_2d(point, ref_coord) ; - - /* Weight in the CPs' list according to coverage and angle */ - double weight = angle / coverage ; - /* Note: this weight is used only to sort the CPs, it has nothing - to do with the angle weight (see weight_cps()) used to compute - the SSs. */ - - /* Create the list entry */ - pair::const_iterator> - angle_cp(angle, ref) ; - pair::const_iterator> > - weight_angle_cp(weight, angle_cp) ; - - /* Rotate the CP's coordinates to know the angle direction */ - Point3D ref_coord_r(ref_coord) ; - ref_coord_r.rotate_2d(rx_coord, origin_angle) ; - // Insert the CP in the right list, according to the direction: - if (ref_coord_r.get_y() < rx_coord.get_y()) - sorted_negative_angles.insert(weight_angle_cp) ; - else - sorted_positive_angles.insert(weight_angle_cp) ; - } -} - - -void Autocalibration::weight_cps() -{ - /* Retrieve the reference CPs & angles */ - ref_cps.clear() ; - map::const_iterator> > - ::const_iterator s ; - s = sorted_negative_angles.begin() ; - if (s != sorted_negative_angles.end()) - init_cp(s) ; - s = sorted_positive_angles.begin() ; - if (s != sorted_positive_angles.end()) - init_cp(s) ; - - /* Weight the CPs */ - if (ref_cps.size() == 1) - ref_cps[0].weight = 100 ; - else if (ref_cps.size() == 2) - weight_2_cps() ; - else - { - ostringstream oss ; - oss << "We should not be here... error when sorting the reference" - << " CPs? (" << ref_cps.size() << " CPs sorted)" ; - throw autocalibration_error(oss.str()) ; - } -} - - -void Autocalibration::init_cp( - map::const_iterator> >::const_iterator s) -{ - struct cp ref ; - ref.cp = &s->second.second->second ; - ref.angle = s->second.first ; // Angle P-REF-RX - ref_cps.push_back(ref) ; -} - - -void Autocalibration::weight_2_cps() -{ - assert(ref_cps.size() > 1) ; - - /* Compute the angle REF1-RX-REF2 */ - double reference_angle = ref_cps[0].angle + ref_cps[1].angle ; - /* Note: the reference angle must be the sum of the two angles - P-RX-REF1 and P-RX-REF2 instead of simply REF1-RX-REF2, to allow - the angle to be within [0;360[° instead of [0;180[°. This is needed - if P-RX-REF1 or P-RX-REF2 are greater than 90°, otherwise the - weights would be wrong. */ - - /* Weight the two CPs */ - if (reference_angle == 0) - ref_cps[0].weight = ref_cps[1].weight = 50 ; - else - { - ref_cps[0].weight = ref_cps[0].angle * 100 / reference_angle ; - if (ref_cps[0].weight > 100) - ref_cps[0].weight = 100 ; - ref_cps[1].weight = 100 - ref_cps[0].weight ; - } -} - - void Autocalibration::compute_ss() { if (Configuration:: @@ -251,120 +119,3 @@ void Autocalibration::compute_ss() else compute_single_packet_ss(0) ; } - - -void Autocalibration::compute_multi_packet_ss() -{ - const cp &ref1 = ref_cps[0] ; - const ReferencePoint &ref1_rp = - Stock::get_reference_point(ref1.cp->get_coordinates()) ; - const vector &ref1_cr = - ref1_rp.get_requests() ; - - /* Search for the first measurement made by RX in ref1_rp */ - const Measurement *rx_measurement = NULL ; - vector::const_iterator cr ; - const string &rx_mac = rx->second.get_mac_addr() ; - for (cr = ref1_cr.begin() ; cr != ref1_cr.end() ; ++cr) - { - rx_measurement = (*cr)->get_measurement(rx_mac) ; - if (rx_measurement) - break ; - } - - // The selected reference CPs are in coverage of RX, therefore - // we should always find a measurement of RX in ref1_rp - assert(rx_measurement) ; - - /* Generate the SS for each packet */ - bool packet_generated = false ; - for (pkt_id_t pkt_id = 1 ; pkt_id <= (*cr)->get_nb_packets() ; - ++pkt_id) - if (compute_single_packet_ss(pkt_id)) - packet_generated = true ; - - if (! packet_generated) - { - if (Configuration::is_configured("verbose")) - cerr << "No packet has been generated for RX CP " << rx_mac - << "... failing back to single packet request. Calibration" - << " request involved : " << **cr << "\n" ; - compute_single_packet_ss(0) ; - } -} - - -/** - * @param pkt_id The number of the packet to create. Must be 0 if all - * the generated reference points contain only one packet. - */ -bool Autocalibration::compute_single_packet_ss(pkt_id_t pkt_id) -{ - /* Distance RX-P */ - const Point3D &rx_coord = rx->second.get_coordinates() ; - float point_dst = rx_coord.distance(point) ; - - /* Compute the consolidated SS */ - double rx_ss = 0 ; - for (unsigned int i = 0 ; i < ref_cps.size() ; ++i) - { - double tmp_ss = compute_weighted_ss(i, pkt_id, point_dst) ; - if (tmp_ss > 0) // error - return false ; - rx_ss += tmp_ss ; - } - - /* Add the SS to the measurements' list */ - const string &rx_mac = rx->second.get_mac_addr() ; - // 0 is not a valid packet ID, so we use 1 if we generate only one - // packet per reference point: - if (pkt_id == 0) - pkt_id = 1 ; - // The Measurement measurements[rx_mac] is created if needed: - measurements[rx_mac].add_ss(pkt_id, rx_ss) ; - // Useful only if the measurement was just created, but it is not - // worth a test: - measurements[rx_mac].set_cp(&rx->second) ; - - return true ; -} - - -/** - * @param cp_idx The index of the CP in #ref_cps. - * @param pkt_id The number of the packet to generate, or 0 if we - * generate only one packet per reference point. - * @param point_dst The distance RX-P. - * - * @returns The weighted SS value in dBm, or 1 in case of error. - */ -double Autocalibration::compute_weighted_ss( - unsigned int cp_idx, pkt_id_t pkt_id, float point_dst) -{ - const cp &ref = ref_cps[cp_idx] ; - const ReferencePoint &rp = - Stock::get_reference_point(ref.cp->get_coordinates()) ; - - /* Friis index */ - const string &rx_mac = rx->second.get_mac_addr() ; - float friis_idx ; - if (pkt_id == 0) - friis_idx = rp.friis_index_for_cp(rx_mac) ; - else - { - friis_idx = rp.friis_index_for_cp(rx_mac, pkt_id) ; - if (friis_idx == 0) - return 1 ; // The packet pkt_id does not exist in rp - } - - /* SS */ - // Constant term - double common_ss = rx->second.friis_constant_term() ; - double ss = - common_ss + - ref.cp->get_trx_power() + - ref.cp->get_antenna_gain() - - 10 * friis_idx * log10(point_dst) ; - - return ss * ref.weight / 100 ; -} diff --git a/owlps-positioner/autocalibration.hh b/owlps-positioner/autocalibration.hh index 297f377..5e3f9d6 100644 --- a/owlps-positioner/autocalibration.hh +++ b/owlps-positioner/autocalibration.hh @@ -15,81 +15,45 @@ #ifndef _OWLPS_POSITIONING_AUTOCALIBRATION_HH_ #define _OWLPS_POSITIONING_AUTOCALIBRATION_HH_ -class CapturePoint ; class Point3D ; #include "measurement.hh" -#include -#include - -/// Generates reference points from autocalibration measurements +/// Base class for the autocalibration methods class Autocalibration { private: - struct cp - { - const CapturePoint *cp ; - float weight ; // Weight of the CP in percents - float angle ; - } ; - - /// Current CP to generate a SS for - std::unordered_map::const_iterator rx ; - /// Angle P-RX-O, O being the origin of the trigonometric circle - float origin_angle ; - /// Selected transmitter CPs - std::vector ref_cps ; - /// Angles of the transmitter CPs (before M on the trigonometric - /// circle) - /** - * Note that the angles are stored in absolute value. - */ - std::multimap::const_iterator> > - sorted_negative_angles ; - /// Angles of the transmitter CPs (after M on the trigonometric circle) - std::multimap::const_iterator> > - sorted_positive_angles ; - /// Characteristics of the virtual mobile - double vmob_gain, vmob_pow ; - /// Generated measurements' list - std::unordered_map measurements ; - - /// Initialises a struct cp with the values from `s` - void init_cp( - std::map::const_iterator> >::const_iterator s) ; - -protected: /// Number of generated "virtual" mobiles static uint32_t nb_virtual_mobiles ; + /// Characteristics of the virtual mobile + double vmob_gain, vmob_pow ; + + /// Work to do before actually generating a SS with generate_ss() + bool init_ss_generation(void) ; + +protected: /// The coordinates of the reference point to generate const Point3D &point ; + /// Current CP to generate a SS for + std::unordered_map::const_iterator rx ; + + /// Generated measurements' list + std::unordered_map measurements ; + /// Generates the SSs for all the CPs - void generate_ss(void) ; - /// Sorts the reference CPs for a receiver CP - void sort_reference_cps(void) ; - /// Computes the weight of the selected CP(s) - void weight_cps(void) ; - /// Weights two CPs according to their angles - void weight_2_cps(void) ; + /** + * Once the preliminary work done, this function should call + * compute_ss() to actually compute the signal strength. + */ + virtual void generate_ss(void) = 0 ; /// Computes the SS of the virtual mobile void compute_ss(void) ; /// Computes a SS with several packets in it - void compute_multi_packet_ss(void) ; + virtual void compute_multi_packet_ss(void) = 0 ; /// Computes a SS with only one packet in it - bool compute_single_packet_ss(pkt_id_t pkt_id) ; - /// Computes a SS according to the weight of the CP - double compute_weighted_ss( - unsigned int cp_idx, pkt_id_t pkt_id, float point_dst) ; + virtual bool compute_single_packet_ss(pkt_id_t pkt_id) = 0 ; public: Autocalibration(const Point3D &_point): point(_point) {} @@ -99,4 +63,3 @@ public: } ; #endif // _OWLPS_POSITIONING_AUTOCALIBRATION_HH_ - diff --git a/owlps-positioner/autocalibrationmesh.cc b/owlps-positioner/autocalibrationmesh.cc new file mode 100644 index 0000000..a3f2c47 --- /dev/null +++ b/owlps-positioner/autocalibrationmesh.cc @@ -0,0 +1,297 @@ +/* + * This file is part of the Owl Positioning System (OwlPS) project. + * It is subject to the copyright notice and license terms in the + * COPYRIGHT.t2t file found in the top-level directory of this + * distribution and at + * http://code.lm7.fr/p/owlps/source/tree/master/COPYRIGHT.t2t + * No part of the OwlPS Project, including this file, may be copied, + * modified, propagated, or distributed except according to the terms + * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be + * distributed along with this file, either separately or by replacing + * this notice by the COPYRIGHT.t2t file's contents. + */ + + +#include "autocalibrationmesh.hh" + +#include "point3d.hh" +#include "capturepoint.hh" +#include "stock.hh" +#include "configuration.hh" +#include "posexcept.hh" + +#include +#include +#include +#include + +using namespace std ; + + + +/* *** Operations *** */ + + +void AutocalibrationMesh::generate_ss() +{ + /* Compute the origin angle P-RX-O */ + const Point3D &rx_coord = rx->second.get_coordinates() ; + Point3D origin(rx_coord) ; + origin.set_x(rx_coord.get_x() + 10) ; + origin_angle = rx_coord.angle_2d(point, origin) ; + if (point.get_y() > rx_coord.get_y()) + origin_angle = -origin_angle ; + + /* Choose the nearest CP(s) in angle */ + sort_reference_cps() ; + // We need at least one reference CP: + if (sorted_negative_angles.empty() && sorted_positive_angles.empty()) + throw autocalibration_error("Not enough CPs in coverage!") ; + + /* Compute the angle weight of the reference CPs */ + weight_cps() ; + + /* Compute the SS that would be received from a mobile at a + * distance of RX-P, in the direction of each reference CP */ + compute_ss() ; +} + + +/** + * The reference (transmitter) CPs are first filtered (floor, coverage), + * then sorted according to their angles with RX and P. + */ +void AutocalibrationMesh::sort_reference_cps() +{ + const Point3D &rx_coord = rx->second.get_coordinates() ; + + sorted_negative_angles.clear() ; + sorted_positive_angles.clear() ; + + for (unordered_map::const_iterator + ref = Stock::cps.begin() ; ref != Stock::cps.end() ; ++ref) + { + if (ref == rx) + continue ; + + /* Skip the CP if it is not at the same floor than the + * receiver CP */ + const Point3D &ref_coord = ref->second.get_coordinates() ; + if (ref_coord.get_z() != rx_coord.get_z()) + continue ; + + /* Skip the CP if it is not in coverage with the receiver CP */ + float coverage = + rx->second.received_calibration_from_cp(ref->second) ; + if (coverage < 1) // Less than 1% coverage is ridiculous! + continue ; + + /* Angle P-RX-REF */ + double angle = rx_coord.angle_2d(point, ref_coord) ; + + /* Weight in the CPs' list according to coverage and angle */ + double weight = angle / coverage ; + /* Note: this weight is used only to sort the CPs, it has nothing + to do with the angle weight (see weight_cps()) used to compute + the SSs. */ + + /* Create the list entry */ + pair::const_iterator> + angle_cp(angle, ref) ; + pair::const_iterator> > + weight_angle_cp(weight, angle_cp) ; + + /* Rotate the CP's coordinates to know the angle direction */ + Point3D ref_coord_r(ref_coord) ; + ref_coord_r.rotate_2d(rx_coord, origin_angle) ; + // Insert the CP in the right list, according to the direction: + if (ref_coord_r.get_y() < rx_coord.get_y()) + sorted_negative_angles.insert(weight_angle_cp) ; + else + sorted_positive_angles.insert(weight_angle_cp) ; + } +} + + +void AutocalibrationMesh::weight_cps() +{ + /* Retrieve the reference CPs & angles */ + ref_cps.clear() ; + map::const_iterator> > + ::const_iterator s ; + s = sorted_negative_angles.begin() ; + if (s != sorted_negative_angles.end()) + init_cp(s) ; + s = sorted_positive_angles.begin() ; + if (s != sorted_positive_angles.end()) + init_cp(s) ; + + /* Weight the CPs */ + if (ref_cps.size() == 1) + ref_cps[0].weight = 100 ; + else if (ref_cps.size() == 2) + weight_2_cps() ; + else + { + ostringstream oss ; + oss << "We should not be here... error when sorting the reference" + << " CPs? (" << ref_cps.size() << " CPs sorted)" ; + throw autocalibration_error(oss.str()) ; + } +} + + +void AutocalibrationMesh::init_cp( + map::const_iterator> >::const_iterator s) +{ + struct cp ref ; + ref.cp = &s->second.second->second ; + ref.angle = s->second.first ; // Angle P-REF-RX + ref_cps.push_back(ref) ; +} + + +void AutocalibrationMesh::weight_2_cps() +{ + assert(ref_cps.size() > 1) ; + + /* Compute the angle REF1-RX-REF2 */ + double reference_angle = ref_cps[0].angle + ref_cps[1].angle ; + /* Note: the reference angle must be the sum of the two angles + P-RX-REF1 and P-RX-REF2 instead of simply REF1-RX-REF2, to allow + the angle to be within [0;360[° instead of [0;180[°. This is needed + if P-RX-REF1 or P-RX-REF2 are greater than 90°, otherwise the + weights would be wrong. */ + + /* Weight the two CPs */ + if (reference_angle == 0) + ref_cps[0].weight = ref_cps[1].weight = 50 ; + else + { + ref_cps[0].weight = ref_cps[0].angle * 100 / reference_angle ; + if (ref_cps[0].weight > 100) + ref_cps[0].weight = 100 ; + ref_cps[1].weight = 100 - ref_cps[0].weight ; + } +} + + +void AutocalibrationMesh::compute_multi_packet_ss() +{ + const cp &ref1 = ref_cps[0] ; + const ReferencePoint &ref1_rp = + Stock::get_reference_point(ref1.cp->get_coordinates()) ; + const vector &ref1_cr = + ref1_rp.get_requests() ; + + /* Search for the first measurement made by RX in ref1_rp */ + const Measurement *rx_measurement = NULL ; + vector::const_iterator cr ; + const string &rx_mac = rx->second.get_mac_addr() ; + for (cr = ref1_cr.begin() ; cr != ref1_cr.end() ; ++cr) + { + rx_measurement = (*cr)->get_measurement(rx_mac) ; + if (rx_measurement) + break ; + } + + // The selected reference CPs are in coverage of RX, therefore + // we should always find a measurement of RX in ref1_rp + assert(rx_measurement) ; + + /* Generate the SS for each packet */ + bool packet_generated = false ; + for (pkt_id_t pkt_id = 1 ; pkt_id <= (*cr)->get_nb_packets() ; + ++pkt_id) + if (compute_single_packet_ss(pkt_id)) + packet_generated = true ; + + if (! packet_generated) + { + if (Configuration::is_configured("verbose")) + cerr << "No packet has been generated for RX CP " << rx_mac + << "... failing back to single packet request. Calibration" + << " request involved : " << **cr << "\n" ; + compute_single_packet_ss(0) ; + } +} + + +/** + * @param pkt_id The number of the packet to create. Must be 0 if all + * the generated reference points contain only one packet. + */ +bool AutocalibrationMesh::compute_single_packet_ss(pkt_id_t pkt_id) +{ + /* Distance RX-P */ + const Point3D &rx_coord = rx->second.get_coordinates() ; + float point_dst = rx_coord.distance(point) ; + + /* Compute the consolidated SS */ + double rx_ss = 0 ; + for (unsigned int i = 0 ; i < ref_cps.size() ; ++i) + { + double tmp_ss = compute_weighted_ss(i, pkt_id, point_dst) ; + if (tmp_ss > 0) // error + return false ; + rx_ss += tmp_ss ; + } + + /* Add the SS to the measurements' list */ + const string &rx_mac = rx->second.get_mac_addr() ; + // 0 is not a valid packet ID, so we use 1 if we generate only one + // packet per reference point: + if (pkt_id == 0) + pkt_id = 1 ; + // The Measurement measurements[rx_mac] is created if needed: + measurements[rx_mac].add_ss(pkt_id, rx_ss) ; + // Useful only if the measurement was just created, but it is not + // worth a test: + measurements[rx_mac].set_cp(&rx->second) ; + + return true ; +} + + +/** + * @param cp_idx The index of the CP in #ref_cps. + * @param pkt_id The number of the packet to generate, or 0 if we + * generate only one packet per reference point. + * @param point_dst The distance RX-P. + * + * @returns The weighted SS value in dBm, or 1 in case of error. + */ +double AutocalibrationMesh::compute_weighted_ss( + unsigned int cp_idx, pkt_id_t pkt_id, float point_dst) +{ + const cp &ref = ref_cps[cp_idx] ; + const ReferencePoint &rp = + Stock::get_reference_point(ref.cp->get_coordinates()) ; + + /* Friis index */ + const string &rx_mac = rx->second.get_mac_addr() ; + float friis_idx ; + if (pkt_id == 0) + friis_idx = rp.friis_index_for_cp(rx_mac) ; + else + { + friis_idx = rp.friis_index_for_cp(rx_mac, pkt_id) ; + if (friis_idx == 0) + return 1 ; // The packet pkt_id does not exist in rp + } + + /* SS */ + // Constant term + double common_ss = rx->second.friis_constant_term() ; + double ss = + common_ss + + ref.cp->get_trx_power() + + ref.cp->get_antenna_gain() - + 10 * friis_idx * log10(point_dst) ; + + return ss * ref.weight / 100 ; +} diff --git a/owlps-positioner/autocalibrationmesh.hh b/owlps-positioner/autocalibrationmesh.hh new file mode 100644 index 0000000..a5608aa --- /dev/null +++ b/owlps-positioner/autocalibrationmesh.hh @@ -0,0 +1,83 @@ +/* + * This file is part of the Owl Positioning System (OwlPS) project. + * It is subject to the copyright notice and license terms in the + * COPYRIGHT.t2t file found in the top-level directory of this + * distribution and at + * http://code.lm7.fr/p/owlps/source/tree/master/COPYRIGHT.t2t + * No part of the OwlPS Project, including this file, may be copied, + * modified, propagated, or distributed except according to the terms + * contained in the COPYRIGHT.t2t file; the COPYRIGHT.t2t file must be + * distributed along with this file, either separately or by replacing + * this notice by the COPYRIGHT.t2t file's contents. + */ + + +#ifndef _OWLPS_POSITIONING_AUTOCALIBRATIONMESH_HH_ +#define _OWLPS_POSITIONING_AUTOCALIBRATIONMESH_HH_ + +class CapturePoint ; +class Point3D ; + +#include "autocalibration.hh" + +#include +#include + +/// Generates reference points in a mesh +class AutocalibrationMesh: public Autocalibration +{ +protected: + struct cp + { + const CapturePoint *cp ; + float weight ; // Weight of the CP in percents + float angle ; + } ; + + /// Angle P-RX-O, O being the origin of the trigonometric circle + float origin_angle ; + /// Selected transmitter CPs + std::vector ref_cps ; + /// Angles of the transmitter CPs (before M on the trigonometric + /// circle) + /** + * Note that the angles are stored in absolute value. + */ + std::multimap::const_iterator> > + sorted_negative_angles ; + /// Angles of the transmitter CPs (after M on the trigonometric circle) + std::multimap::const_iterator> > + sorted_positive_angles ; + + /// Initialises a struct cp with the values from `s` + void init_cp( + std::map::const_iterator> >::const_iterator s) ; + + /// Generates the SSs for all the CPs + void generate_ss(void) ; + /// Sorts the reference CPs for a receiver CP + void sort_reference_cps(void) ; + /// Computes the weight of the selected CP(s) + void weight_cps(void) ; + /// Weights two CPs according to their angles + void weight_2_cps(void) ; + /// Computes a SS with several packets in it + void compute_multi_packet_ss(void) ; + /// Computes a SS with only one packet in it + bool compute_single_packet_ss(pkt_id_t pkt_id) ; + /// Computes a SS according to the weight of the CP + double compute_weighted_ss( + unsigned int cp_idx, pkt_id_t pkt_id, float point_dst) ; + +public: + AutocalibrationMesh(const Point3D &_point): Autocalibration(_point) {} +} ; + +#endif // _OWLPS_POSITIONING_AUTOCALIBRATIONMESH_HH_ diff --git a/owlps-positioner/stock.cc b/owlps-positioner/stock.cc index daadeeb..935b5c5 100644 --- a/owlps-positioner/stock.cc +++ b/owlps-positioner/stock.cc @@ -17,6 +17,7 @@ #include "posexcept.hh" #include "area.hh" #include "csvstringreader.hh" +#include "autocalibrationmesh.hh" #include @@ -503,7 +504,7 @@ void Stock::generate_reference_points_list() */ void Stock::generate_reference_point(const Point3D &coord) { - Autocalibration ac(coord) ; + AutocalibrationMesh ac(coord) ; try { ac.generate_reference_point() ; diff --git a/owlps-positioner/stock.hh b/owlps-positioner/stock.hh index e3ba60f..a490b2c 100644 --- a/owlps-positioner/stock.hh +++ b/owlps-positioner/stock.hh @@ -15,7 +15,6 @@ #ifndef _OWLPS_POSITIONING_STOCK_HH_ #define _OWLPS_POSITIONING_STOCK_HH_ -#include "autocalibration.hh" #include "building.hh" #include "waypoint.hh" #include "mobile.hh" @@ -30,6 +29,7 @@ class Stock { friend class Autocalibration ; + friend class AutocalibrationMesh ; private: /// List of known Building