From 88aaded78c85871ee48849c6d8bde1bd3050c678 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 15 Jun 2011 15:13:18 +0200 Subject: [PATCH 01/64] [Positioning] Add Stock::get_reference_point() --- owlps-positioning/src/stock.cc | 18 ++++++++++++++++++ owlps-positioning/src/stock.hh | 3 +++ 2 files changed, 21 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index f8a01b5..94c4137 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -243,6 +243,24 @@ void Stock::update_all_friis_indexes() /* *** ReferencePoint operations *** */ +/** + * @param point Coordinates of the wanted ReferencePoint. + * @return The ReferencePoint at the given coordinates, if found. + * @throw element_not_found is thrown if no ReferencePoint exists at the + * given coordinates. + */ +const ReferencePoint& Stock:: +get_reference_point(const ReferencePoint &point) +{ + unordered_set::const_iterator i = + reference_points.find(point) ; + if (i != reference_points.end()) + return *i ; + throw element_not_found("No ReferencePoint with coordinates " + + static_cast(point) + "!") ; +} + + const ReferencePoint& Stock:: find_create_reference_point(const ReferencePoint &point) { diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index a23ba88..a22e088 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -99,6 +99,9 @@ public: //@{ /// Returns the number of reference points static unsigned int nb_reference_points(void) ; + /// Reads the ReferencePoint at the given coordinates + static const ReferencePoint& + get_reference_point(const ReferencePoint &point) ; /// Searches for a ReferencePoint and adds it if it does not exist static const ReferencePoint& find_create_reference_point(const ReferencePoint &point) ; From f84276d8d7d705baf33407ad8ad504b313f45443 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 15 Jun 2011 15:17:01 +0200 Subject: [PATCH 02/64] [Positioning] ReferencePoint::average_measurements() Add double ReferencePoint::average_measurements(string mac_transmitter), that allows to get the average of all the Measurements sent by a given transmitter. Add, as protected functions, get_all_measurements(string mac_transmitter) and get_requests(string mac_transmitter), that do the same as get_all_measurements(void) and get_requests(void), but filtering on the transmitter of the packets. --- owlps-positioning/src/referencepoint.cc | 62 +++++++++++++++++++++++++ owlps-positioning/src/referencepoint.hh | 7 +++ 2 files changed, 69 insertions(+) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index 7feaf04..9a03900 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -25,6 +25,26 @@ ReferencePoint::~ReferencePoint() /* *** Accessors *** */ +double ReferencePoint:: +average_measurements(const std::string &mac_transmitter) const +{ + unordered_map measurements( + get_all_measurements(mac_transmitter)) ; + double avg = 0 ; + int n_ss = 0 ; + + for (unordered_map::const_iterator i = + measurements.begin() ; + i != measurements.end() ; ++i) + { + avg += i->second.get_average_ss() ; + ++n_ss ; + } + + return (avg / n_ss) ; +} + + unordered_map ReferencePoint:: get_all_measurements() const { @@ -45,6 +65,48 @@ get_all_measurements() const } +unordered_map ReferencePoint:: +get_all_measurements(const string &mac_transmitter) const +{ + unordered_map all ; + vector requests_trx( + get_requests(mac_transmitter)) ; + + for (vector::const_iterator i = + requests_trx.begin() ; + i != requests_trx.end() ; ++i) + { + unordered_map measurements = + (*i)->get_measurements() ; + for (unordered_map::const_iterator j = + measurements.begin() ; j != measurements.end() ; ++j) + if (! all.insert(*j).second) + all[j->first].merge(j->second) ; + } + + return all ; +} + + +/** + * @param mac_transmitter The MAC address of the transmitting mobile. + * @return A vector containing all the requests sent by the mobile. + * The returned vector is empty if no request was sent by the mobile. + */ +const vector ReferencePoint:: +get_requests(const string &mac_transmitter) const +{ + vector res ; + + for (vector::const_iterator i = requests.begin() ; + i != requests.end() ; ++i) + if ((*i)->get_mobile()->get_mac_addr() == mac_transmitter) + res.push_back(*i) ; + + return res ; +} + + /* *** Operations *** */ diff --git a/owlps-positioning/src/referencepoint.hh b/owlps-positioning/src/referencepoint.hh index 5dcc84a..0f8e232 100644 --- a/owlps-positioning/src/referencepoint.hh +++ b/owlps-positioning/src/referencepoint.hh @@ -25,6 +25,12 @@ protected: //@{ std::tr1::unordered_map get_all_measurements(void) const ; + /// Returns all the measurements sent by the given mobile + std::tr1::unordered_map + get_all_measurements(const std::string &mac_transmitter) const ; + /// Returns the calibration requests sent by the given mobile + const std::vector get_requests( + const std::string &mac_transmitter) const ; //@} public: @@ -42,6 +48,7 @@ public: /** @name Read accessors */ //@{ const std::vector& get_requests(void) const ; + double average_measurements(const std::string &mac_transmitter) const ; //@} /** @name Write accessors */ From 71784342e76a914d083628557ce1f291dc524a41 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 15 Jun 2011 15:30:49 +0200 Subject: [PATCH 03/64] [Positioning] Add Stock::ap_matrix_get_ss() Add double Stock::ap_matrix_get_ss(transmitter, receiver). This is the first step to handle self-calibration in owlps-positioning. The idea is to simulates a square matrix of the listeners, with the transmitters in one dimension and the receivers in the other dimension. matrix[transmitter][receiver] is the signal strength received by 'receiver' from 'transmitter'. The purpose of Stock::ap_matrix_get_ss() is precisely to access the entry matrix[transmitter][receiver]. Note that the access is read-only, as the pseudo-matrix is (or will be) filled by the standard mechanism of (auto)calibration requests and measurements stored in Stock. --- owlps-positioning/src/stock.cc | 11 +++++++++++ owlps-positioning/src/stock.hh | 2 ++ 2 files changed, 13 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 94c4137..158c3f8 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -239,6 +239,17 @@ void Stock::update_all_friis_indexes() } +double Stock::ap_matrix_get_ss(const std::string &mac_transmitter, + const std::string &mac_receiver) +{ + const AccessPoint &receiver = get_ap(mac_receiver) ; + const ReferencePoint &rp = + get_reference_point(receiver.get_coordinates()) ; + + return rp.average_measurements(mac_transmitter) ; +} + + /* *** ReferencePoint operations *** */ diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index a22e088..86f4f1d 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -93,6 +93,8 @@ public: static AccessPoint& getw_ap(const std::string &mac) ; /// Updates the friis indexes of all the APs static void update_all_friis_indexes(void) ; + static double ap_matrix_get_ss(const std::string &mac_transmitter, + const std::string &mac_receiver) ; //@} /** @name ReferencePoint operations */ From 0dd57b8ea7d08e846bb6b83655053d62f8f4046d Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 16 Jun 2011 19:03:42 +0200 Subject: [PATCH 04/64] [Positioning] InputUDPSocket: use AP's coordinates Use the transmitting AP's coordinates when receiving an autocalibration request that does not contain the coordinates. --- owlps-positioning/src/inputudpsocket.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index 174804d..69bfa2f 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -149,6 +149,15 @@ const Request& InputUDPSocket::get_next_request() if (request.type == OWL_REQUEST_CALIBRATION || request.type == OWL_REQUEST_AUTOCALIBRATION) { + AccessPoint &transmitter = + const_cast(Stock::find_create_ap(mac_mobile)) ; + + // If an autocalibration request does not contain the coordinates + // of the AP, we use the current coordinates of the AP as + // ReferencePoint. + if (request.type == OWL_REQUEST_AUTOCALIBRATION && ! position) + position = transmitter.get_coordinates() ; + const ReferencePoint &reference_point = Stock::find_create_reference_point(position) ; current_request_to_calibration_request(&reference_point, From de9513e4b424084dae0b1e8b7524a774791cb55b Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 16 Jun 2011 19:05:14 +0200 Subject: [PATCH 05/64] [Positioning] Add option update-ap-coordinates-online In InputUDPSocket, update the AP's coordinates when receiving a calibration or autocalibration request that contains the coordinates. This is done if the option positioning.update-ap-coordinates-online is activated. --- owlps-positioning/cfg/owlps-positioning.cfg | 6 ++++++ owlps-positioning/src/inputudpsocket.cc | 9 +++++++++ owlps-positioning/src/userinterface.cc | 5 +++++ 3 files changed, 20 insertions(+) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index 321fcfd..b6e5580 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -59,6 +59,12 @@ csv-file = /tmp/owlps-positioning.log # request is compared directly to each calibration request. #radar-average-reference-points = false +# When receiving a calibration or autocalibration request from an AP, +# containing the transmiter's coordinates, memorise the new AP's +# coordinates. +# This is unactivated by default for the sake of security. +#update-ap-coordinates-online = false + [output] # This is the default output if none is specified. diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index 69bfa2f..a40128e 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -1,6 +1,7 @@ #include "inputudpsocket.hh" #include "posexcept.hh" #include "stock.hh" +#include "configuration.hh" #include @@ -158,6 +159,14 @@ const Request& InputUDPSocket::get_next_request() if (request.type == OWL_REQUEST_AUTOCALIBRATION && ! position) position = transmitter.get_coordinates() ; + // Update the AP's coordinates if allowed. A 'false' position + // (i.e. 0;0;0) is only set for calibration requests, to avoid + // setting the coordinates to 0;0;0 if an autocalibration + // request that does not contain the coordinates is received. + else if (Configuration:: + bool_value("positioning.update-ap-coordinates-online")) + transmitter.set_coordinates(position) ; + const ReferencePoint &reference_point = Stock::find_create_reference_point(position) ; current_request_to_calibration_request(&reference_point, diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index b27990d..b60432f 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -186,6 +186,11 @@ void UserInterface::fill_positioning_options() " before to compute the SS distance." " The default is false, i.e the positioning request is compared" " directly to each calibration request.") + ("positioning.update-ap-coordinates-online", + po::value()->default_value(false), + "Allow AP's coordinates to be updated when a calibration request" + " with new coordinates is received from the AP (default is false," + " for security purposes).") ; file_options->add(options) ; From 586cfdb77e1ae6c83cb35df4662c36dd58d682f5 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 17 Jun 2011 12:35:14 +0200 Subject: [PATCH 06/64] [Positioning] Stock::store_calibration_request() InputDataReader::stock_calibration_request() becomes Stock::store_calibration_request(), so other classes can use it. --- owlps-positioning/src/inputdatareader.cc | 15 +++------------ owlps-positioning/src/inputdatareader.hh | 2 -- owlps-positioning/src/stock.cc | 9 +++++++++ owlps-positioning/src/stock.hh | 4 ++++ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/owlps-positioning/src/inputdatareader.cc b/owlps-positioning/src/inputdatareader.cc index 7c07552..0c4c9c3 100644 --- a/owlps-positioning/src/inputdatareader.cc +++ b/owlps-positioning/src/inputdatareader.cc @@ -193,27 +193,18 @@ void InputDataReader::read_from_reference_points_media() while (! (*i)->eof()) { const Request &request = (*i)->get_next_request() ; + if (! request) continue ; + CalibrationRequest *calibration_request = dynamic_cast( const_cast(&request)) ; - if (calibration_request == NULL) cerr << "Warning! Invalid calibration request at line " << (*i)->get_current_line_nb() << endl ; else - stock_calibration_request(*calibration_request) ; + Stock::store_calibration_request(*calibration_request) ; } } } - - -void InputDataReader:: -stock_calibration_request(const CalibrationRequest &request) const -{ - const CalibrationRequest &calibration_request = - Stock::find_create_calibration_request(request) ; - - calibration_request.reference_point_backward_link() ; -} diff --git a/owlps-positioning/src/inputdatareader.hh b/owlps-positioning/src/inputdatareader.hh index 3db777c..1808679 100644 --- a/owlps-positioning/src/inputdatareader.hh +++ b/owlps-positioning/src/inputdatareader.hh @@ -24,8 +24,6 @@ protected: void initialise_reference_points_media(void) ; void initialise_reference_points_csv(void) ; void read_from_reference_points_media(void) ; - void stock_calibration_request( - const CalibrationRequest &request) const ; public: InputDataReader(void) ; diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 158c3f8..24be46c 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -314,6 +314,15 @@ closest_reference_point(const Request &request) /* *** CalibrationRequest operations *** */ +void Stock:: +store_calibration_request(const CalibrationRequest &request) +{ + const CalibrationRequest &calibration_request = + find_create_calibration_request(request) ; + calibration_request.reference_point_backward_link() ; +} + + const CalibrationRequest& Stock:: find_create_calibration_request(const CalibrationRequest &request) { diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 86f4f1d..5f3629d 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -117,6 +117,10 @@ public: //@{ /// Returns the number of calibration requests static unsigned int nb_calibration_requests(void) ; + /// \brief Searches for a CalibrationRequest, adds it if it does + /// not exist, and links it to its reference point + static void store_calibration_request( + const CalibrationRequest &request) ; /// Searches for a CalibrationRequest and adds it if it does not exist static const CalibrationRequest& find_create_calibration_request(const CalibrationRequest &request) ; From b8bd2acf44a0e8fcfb7aa71ab8fe5250cc6c5206 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 17 Jun 2011 16:02:19 +0200 Subject: [PATCH 07/64] [Positioning] Add option accept-new-calibration-requests The option positioning.accept-new-calibration-requests allows the calibration requests sent during the positioning phase to be added to the Stock. They are added to the calibration requests read by InputDataReader during the start-up phase. --- owlps-positioning/cfg/owlps-positioning.cfg | 9 +++++++++ owlps-positioning/src/input.cc | 16 +++++++++++++++- owlps-positioning/src/userinterface.cc | 7 +++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index b6e5580..9bcc936 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -59,6 +59,15 @@ csv-file = /tmp/owlps-positioning.log # request is compared directly to each calibration request. #radar-average-reference-points = false +# This option allows the calibration requests sent during the +# positioning phase to be added to the calibration request's list. They +# are added to the calibration requests read by InputDataReader during +# the start-up phase. If this option is not activated, the calibration +# requests are handled as positioning requests. +# This option must be activated for the self-calibration to work, but +# it is not activated by default for security purposes. +#accept-new-calibration-requests = false + # When receiving a calibration or autocalibration request from an AP, # containing the transmiter's coordinates, memorise the new AP's # coordinates. diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index 2196d4b..3c46dea 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -113,8 +113,22 @@ const Request& Input::get_next_request() const { if (! eof()) { - medium->get_next_request() ; + const Request& request = medium->get_next_request() ; log_current_request() ; + + // If the request is a calibration request, add it to the Stock + // (if allowed) + if (Configuration:: + bool_value("positioning.accept-new-calibration-requests")) + { + if (! request) // Skip the request if empty + return request ; + CalibrationRequest *calibration_request = + dynamic_cast( + const_cast(&request)) ; + if (calibration_request != NULL) + Stock::store_calibration_request(*calibration_request) ; + } } return medium->get_current_request() ; diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index b60432f..15a528b 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -186,6 +186,13 @@ void UserInterface::fill_positioning_options() " before to compute the SS distance." " The default is false, i.e the positioning request is compared" " directly to each calibration request.") + ("positioning.accept-new-calibration-requests", + po::value()->default_value(false), + "Add the calibration requests received during the run-time to" + " the calibration requests' list; this is required for the" + " self-calibration. If unactivated, the calibration requests" + " are handled as positioning requests (default is unactivated," + " for security purposes).") ("positioning.update-ap-coordinates-online", po::value()->default_value(false), "Allow AP's coordinates to be updated when a calibration request" From 0491fe0a62d23fc688b8e754dc01e195d8aa43a3 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 20 Jun 2011 11:43:17 +0200 Subject: [PATCH 08/64] [Positioning] Input: del RP's requests on new CR When a new calibration request is received, all the calibration requests of the corresponding reference point are now cleared prior to add the new request. We should probably use a timeout to delete only the old calibration requests and keep the recent ones. --- owlps-positioning/src/calibrationrequest.cc | 6 ++++++ owlps-positioning/src/calibrationrequest.hh | 2 ++ owlps-positioning/src/input.cc | 5 ++++- owlps-positioning/src/referencepoint.cc | 14 ++++++++++++++ owlps-positioning/src/referencepoint.hh | 2 ++ owlps-positioning/src/stock.cc | 7 +++++++ owlps-positioning/src/stock.hh | 3 +++ 7 files changed, 38 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/src/calibrationrequest.cc b/owlps-positioning/src/calibrationrequest.cc index cb33471..0a37080 100644 --- a/owlps-positioning/src/calibrationrequest.cc +++ b/owlps-positioning/src/calibrationrequest.cc @@ -30,6 +30,12 @@ CalibrationRequest(const Request &source, /* *** Write accessors *** */ +void CalibrationRequest::reference_point_delete_requests() const +{ + reference_point->delete_requests() ; +} + + void CalibrationRequest::reference_point_backward_link() const { reference_point->add_request(this) ; diff --git a/owlps-positioning/src/calibrationrequest.hh b/owlps-positioning/src/calibrationrequest.hh index 68a378a..0f0147f 100644 --- a/owlps-positioning/src/calibrationrequest.hh +++ b/owlps-positioning/src/calibrationrequest.hh @@ -41,6 +41,8 @@ public: void set_reference_point(const ReferencePoint *_rp) ; /// Adds the CalibrationRequest to the #reference_point list of requests void reference_point_backward_link(void) const ; + /// Deletes all the requests of #reference_point + void reference_point_delete_requests(void) const ; void clear(void) ; //@} diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index 3c46dea..e736ab3 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -127,7 +127,10 @@ const Request& Input::get_next_request() const dynamic_cast( const_cast(&request)) ; if (calibration_request != NULL) - Stock::store_calibration_request(*calibration_request) ; + { + calibration_request->reference_point_delete_requests() ; + Stock::store_calibration_request(*calibration_request) ; + } } } diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index 9a03900..c55babe 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -107,6 +107,20 @@ get_requests(const string &mac_transmitter) const } +/** + * Note that the requests pointed by the elements of #requests are + * actually deleted from the Stock. + */ +void ReferencePoint::delete_requests() +{ + for (vector::iterator i = requests.begin() ; + i != requests.end() ; ++i) + Stock::delete_calibration_request(**i) ; + + requests.clear() ; +} + + /* *** Operations *** */ diff --git a/owlps-positioning/src/referencepoint.hh b/owlps-positioning/src/referencepoint.hh index 0f8e232..efd26a8 100644 --- a/owlps-positioning/src/referencepoint.hh +++ b/owlps-positioning/src/referencepoint.hh @@ -55,6 +55,8 @@ public: //@{ /// Adds a Request to the \link #requests request list\endlink void add_request(const CalibrationRequest *cm) ; + /// Deletes all the requests contained in #requests + void delete_requests(void) ; //@} /** @name Operations */ diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 24be46c..ca3239f 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -323,6 +323,13 @@ store_calibration_request(const CalibrationRequest &request) } +void Stock:: +delete_calibration_request(const CalibrationRequest &request) +{ + calibration_requests.erase(request) ; +} + + const CalibrationRequest& Stock:: find_create_calibration_request(const CalibrationRequest &request) { diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 5f3629d..b7de8c1 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -121,6 +121,9 @@ public: /// not exist, and links it to its reference point static void store_calibration_request( const CalibrationRequest &request) ; + /// Deletes a CalibrationRequest + static void delete_calibration_request( + const CalibrationRequest &request) ; /// Searches for a CalibrationRequest and adds it if it does not exist static const CalibrationRequest& find_create_calibration_request(const CalibrationRequest &request) ; From 05859da49b3dc8b183c3d33df0a5be5a24e95514 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 11:05:58 +0200 Subject: [PATCH 09/64] [Positioning] Reorder 2 headers in stock.hh --- owlps-positioning/src/stock.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index b7de8c1..33b1021 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -83,11 +83,11 @@ public: static unsigned int nb_aps(void) ; /// Reads the AccessPoint corresponding to a given MAC address static const AccessPoint& get_ap(const std::string &mac) ; - /// Searches for an AccessPoint and create it if it does not exist - static const AccessPoint& find_create_ap(const AccessPoint &source) ; /// \brief Searches for an AccessPoint given its MAC address and /// creates it if it does not exist static const AccessPoint& find_create_ap(const std::string &mac) ; + /// Searches for an AccessPoint and create it if it does not exist + static const AccessPoint& find_create_ap(const AccessPoint &source) ; /// \brief Returns a reference to the AccessPoint corresponding to a /// given MAC address static AccessPoint& getw_ap(const std::string &mac) ; From e9e8308a9cd953ce9e84b97293866e3f45719f3e Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 11:32:13 +0200 Subject: [PATCH 10/64] [Positioning] PosUtil: add string functions Add PosUtil::to_upper(string) and PosUtil::assert_uppercase(string). --- owlps-positioning/src/posutil.hh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/owlps-positioning/src/posutil.hh b/owlps-positioning/src/posutil.hh index 22d1cbd..8e56ebb 100644 --- a/owlps-positioning/src/posutil.hh +++ b/owlps-positioning/src/posutil.hh @@ -4,6 +4,7 @@ class Measurement ; #include +#include /// Utilitary class class PosUtil @@ -29,6 +30,34 @@ public: /// Converts a Wi-Fi channel to the corresponding frequency in Hz static unsigned long wifi_channel_to_hz(const unsigned long &channel) ; //@} + + /** @name Strings */ + //@{ + static void to_upper(std::string &str) ; + static void assert_uppercase(const std::string &str) ; + //@} } ; + + +/* *** Strings *** */ + + +inline void PosUtil::to_upper(std::string &str) +{ + boost::to_upper(str) ; +} + + +inline void PosUtil::assert_uppercase(const std::string &str) +{ +#ifndef NDEBUG + std::string str_up(str) ; + to_upper(str_up) ; + assert(str_up == str) ; +#endif // NDEBUG +} + + + #endif // _OWLPS_POSITIONING_POSUTIL_HH_ From 37997242c5a553425bb6378338ef3c9335471d9f Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 11:37:33 +0200 Subject: [PATCH 11/64] [Positioning] Uppercase all MAC addresses on input --- .../src/accesspointsreadercsv.cc | 1 + owlps-positioning/src/inputcsv.cc | 2 ++ owlps-positioning/src/inputudpsocket.cc | 10 ++++--- owlps-positioning/src/wifidevice.hh | 29 +++++++++++++++---- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/owlps-positioning/src/accesspointsreadercsv.cc b/owlps-positioning/src/accesspointsreadercsv.cc index a33aa52..858b9a3 100644 --- a/owlps-positioning/src/accesspointsreadercsv.cc +++ b/owlps-positioning/src/accesspointsreadercsv.cc @@ -33,6 +33,7 @@ void AccessPointsReaderCSV::process_access_point_line() string mac ; if (! file.read_field(mac)) throw malformed_input_data("Cannot read access point MAC address!") ; + PosUtil::to_upper(mac) ; Point3D coord ; if (! file.read_point3d(coord)) diff --git a/owlps-positioning/src/inputcsv.cc b/owlps-positioning/src/inputcsv.cc index 99a67e1..3a3ce78 100644 --- a/owlps-positioning/src/inputcsv.cc +++ b/owlps-positioning/src/inputcsv.cc @@ -45,6 +45,7 @@ const Request& InputCSV::get_next_request() cerr << "InputCSV: cannot read mac_mobile.\n" ; return *current_request ; } + PosUtil::to_upper(mac_mobile) ; const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ; current_request->set_mobile(&mobile) ; @@ -114,6 +115,7 @@ const Request& InputCSV::get_next_request() cerr << "InputCSV: cannot read mac_ap.\n" ; return *current_request ; } + PosUtil::to_upper(mac_ap) ; const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(ss) ; diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index a40128e..8009308 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -107,8 +107,9 @@ const Request& InputUDPSocket::get_next_request() request.nb_info = ntohs(request.nb_info) ; // Mobile MAC - const char *const mac_mobile = - owl_mac_bytes_to_string(request.mobile_mac_addr_bytes) ; + string mac_mobile( + owl_mac_bytes_to_string(request.mobile_mac_addr_bytes)) ; + PosUtil::to_upper(mac_mobile) ; const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ; current_request->set_mobile(&mobile) ; @@ -136,8 +137,9 @@ const Request& InputUDPSocket::get_next_request() current_request->clear() ; return *current_request ; } - const char *const mac_ap = - owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes) ; + string mac_ap( + owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ; + PosUtil::to_upper(mac_ap) ; const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(static_cast diff --git a/owlps-positioning/src/wifidevice.hh b/owlps-positioning/src/wifidevice.hh index 3ee0b41..6777fb5 100644 --- a/owlps-positioning/src/wifidevice.hh +++ b/owlps-positioning/src/wifidevice.hh @@ -1,6 +1,8 @@ #ifndef _OWLPS_POSITIONING_WIFIDEVICE_HH_ #define _OWLPS_POSITIONING_WIFIDEVICE_HH_ +#include "posutil.hh" + #include #include @@ -21,12 +23,10 @@ protected: float trx_power ; ///< Transmit power in dBm public: - WifiDevice(const std::string &_ip_addr = "", - const std::string &_mac_addr = "", - const float _antenna_gain = WIFIDEVICE_DEFAULT_ANTENNA_GAIN, - const float _trx_power = WIFIDEVICE_DEFAULT_TRX_POWER): - ip_addr(_ip_addr), mac_addr(_mac_addr), - antenna_gain(_antenna_gain), trx_power(_trx_power) {} + WifiDevice(const std::string &_ip_addr, + const std::string &_mac_addr, + const float _antenna_gain, + const float _trx_power) ; WifiDevice(const WifiDevice &source): ip_addr(source.ip_addr), mac_addr(source.mac_addr), @@ -63,6 +63,22 @@ public: +/* *** Constructors *** */ + + +inline WifiDevice:: +WifiDevice(const std::string &_ip_addr = "", + const std::string &_mac_addr = "", + const float _antenna_gain = WIFIDEVICE_DEFAULT_ANTENNA_GAIN, + const float _trx_power = WIFIDEVICE_DEFAULT_TRX_POWER): + ip_addr(_ip_addr), mac_addr(_mac_addr), + antenna_gain(_antenna_gain), trx_power(_trx_power) +{ + PosUtil::assert_uppercase(mac_addr) ; +} + + + /* *** Read accessors *** */ @@ -102,6 +118,7 @@ inline void WifiDevice::set_ip_addr(const std::string &_ip_addr) inline void WifiDevice::set_mac_addr(const std::string &_mac_addr) { + PosUtil::assert_uppercase(_mac_addr) ; mac_addr = _mac_addr ; } From 68b97451aa9826484c82a4458d8c48f7c7ae1f14 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 14:53:23 +0200 Subject: [PATCH 12/64] [Positioning] Print new created APs when verbose --- owlps-positioning/src/stock.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index ca3239f..e0d8df9 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -1,4 +1,5 @@ #include "stock.hh" +#include "configuration.hh" #include "posexcept.hh" using namespace std ; @@ -179,6 +180,12 @@ const AccessPoint& Stock::find_create_ap(const string &mac) AccessPoint &ap = aps[mac] ; ap.set_mac_addr(mac) ; + + if (Configuration::is_configured("verbose")) + cerr + << "New AP « " << mac + << " » (total: " << nb_aps() << " APs).\n" ; + return ap ; } From 2b1248fbece8d35585e19aca5488f6e10e19722e Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 16:13:44 +0200 Subject: [PATCH 13/64] [Positioning] Add Stock::ap_exists() --- owlps-positioning/src/stock.cc | 13 +++++++++++++ owlps-positioning/src/stock.hh | 2 ++ 2 files changed, 15 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index e0d8df9..dee9a44 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -152,6 +152,19 @@ const Mobile& Stock::find_create_mobile(const string &mac) /* *** 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 \em true if an AP with this MAC address exists. + * @return \em false if this MAC address was not found. + */ +bool Stock::ap_exists(const std::string &mac) +{ + unordered_map::const_iterator i = aps.find(mac) ; + return i != aps.end() ; +} + + /** * @param mac The MAC address of the AccessPoint to search for. * It must be a valid MAC address, as no check is performed. diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 33b1021..ab4cbab 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -81,6 +81,8 @@ public: //@{ /// Returns the number of access points static unsigned int nb_aps(void) ; + /// Verify the existence of an AP + static bool ap_exists(const std::string &mac) ; /// Reads the AccessPoint corresponding to a given MAC address static const AccessPoint& get_ap(const std::string &mac) ; /// \brief Searches for an AccessPoint given its MAC address and From 1f46075aa3b8405ca249177219cea59378a58d49 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 16:45:36 +0200 Subject: [PATCH 14/64] [Positioning] Add option accept-new-aps The option positioning.accept-new-aps allows the program to add on-line APs that are not declared in the APs' configuration file. --- owlps-positioning/cfg/owlps-positioning.cfg | 7 +++++++ owlps-positioning/src/inputcsv.cc | 5 +++++ owlps-positioning/src/inputudpsocket.cc | 12 ++++++++++-- owlps-positioning/src/userinterface.cc | 5 +++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index 9bcc936..b45091d 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -68,6 +68,13 @@ csv-file = /tmp/owlps-positioning.log # it is not activated by default for security purposes. #accept-new-calibration-requests = false +# This option allows to create a new AP when a request is captured by an +# AP which is not currently in the APs' list (i.e. not declared in the +# APs' configuration file), or when a self-calibration request is sent +# by an unknown AP. +# It is unactivated by default for the sake of security. +#accept-new-aps = false + # When receiving a calibration or autocalibration request from an AP, # containing the transmiter's coordinates, memorise the new AP's # coordinates. diff --git a/owlps-positioning/src/inputcsv.cc b/owlps-positioning/src/inputcsv.cc index 3a3ce78..99a56f0 100644 --- a/owlps-positioning/src/inputcsv.cc +++ b/owlps-positioning/src/inputcsv.cc @@ -116,6 +116,11 @@ const Request& InputCSV::get_next_request() return *current_request ; } PosUtil::to_upper(mac_ap) ; + + if (! Configuration::bool_value("positioning.accept-new-aps") && + ! Stock::ap_exists(mac_ap)) + continue ; + const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(ss) ; diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index 8009308..f8440de 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -140,6 +140,11 @@ const Request& InputUDPSocket::get_next_request() string mac_ap( owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ; PosUtil::to_upper(mac_ap) ; + + if (! Configuration::bool_value("positioning.accept-new-aps") && + ! Stock::ap_exists(mac_ap)) + continue ; + const AccessPoint &ap = Stock::find_create_ap(mac_ap) ; measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(static_cast @@ -149,8 +154,11 @@ const Request& InputUDPSocket::get_next_request() current_request->set_measurements(measurements) ; // Calibration request? - if (request.type == OWL_REQUEST_CALIBRATION || - request.type == OWL_REQUEST_AUTOCALIBRATION) + if ((request.type == OWL_REQUEST_CALIBRATION || + request.type == OWL_REQUEST_AUTOCALIBRATION) + && + (Configuration::bool_value("positioning.accept-new-aps") || + Stock::ap_exists(mac_mobile))) { AccessPoint &transmitter = const_cast(Stock::find_create_ap(mac_mobile)) ; diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 15a528b..0353477 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -193,6 +193,11 @@ void UserInterface::fill_positioning_options() " self-calibration. If unactivated, the calibration requests" " are handled as positioning requests (default is unactivated," " for security purposes).") + ("positioning.accept-new-aps", + po::value()->default_value(false), + "When receiving requests, add unknown APs (APs which are not" + " declared in the APs' configuration file) to the APs' list" + " (default is false, for security purposes).") ("positioning.update-ap-coordinates-online", po::value()->default_value(false), "Allow AP's coordinates to be updated when a calibration request" From 0df91eaa9499be9866f8cbcfb34b3e6924319038 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 17:32:08 +0200 Subject: [PATCH 15/64] [Positioning] Input*: skip requests without measurements --- owlps-positioning/src/inputcsv.cc | 6 +++++- owlps-positioning/src/inputudpsocket.cc | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/owlps-positioning/src/inputcsv.cc b/owlps-positioning/src/inputcsv.cc index 99a56f0..47764fe 100644 --- a/owlps-positioning/src/inputcsv.cc +++ b/owlps-positioning/src/inputcsv.cc @@ -125,7 +125,11 @@ const Request& InputCSV::get_next_request() measurements[mac_ap].set_ap(&ap) ; measurements[mac_ap].add_ss(ss) ; } - + if (measurements.empty()) + { + current_request->clear() ; + return *current_request ; + } current_request->set_measurements(measurements) ; // Calibration request? diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index f8440de..b63f1e5 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -150,7 +150,11 @@ const Request& InputUDPSocket::get_next_request() measurements[mac_ap].add_ss(static_cast (request_info.antenna_signal_dbm)) ; } - + if (measurements.empty()) + { + current_request->clear() ; + return *current_request ; + } current_request->set_measurements(measurements) ; // Calibration request? From d43267fcd3e5fd2da92d3794cd08f07ff51eb53b Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 17:33:44 +0200 Subject: [PATCH 16/64] [Positioning] Positioning: catch compute exceptions Catch the exception potentially thrown by PositioningAlgorithm::compute(). --- owlps-positioning/src/positioning.cc | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/src/positioning.cc b/owlps-positioning/src/positioning.cc index 38480e0..0e94cd9 100644 --- a/owlps-positioning/src/positioning.cc +++ b/owlps-positioning/src/positioning.cc @@ -97,7 +97,21 @@ void Positioning::loop() for (algo = algorithms.begin() ; algo != algorithms.end() ; ++algo) { - Result res((*algo)->compute(request)) ; + Result res ; + + try + { + res = (*algo)->compute(request) ; + } + catch (exception &e) + { + cerr + << "Cannot compute with algorithm " + << (*algo)->get_name() << ": « " + << e.what() << " »\n" ; + continue ; + } + if (compute_error) res.compute_error(real_position) ; else if ((*algo)->get_name() == "Real") @@ -105,6 +119,7 @@ void Positioning::loop() compute_error = true ; real_position = res.get_position() ; } + results.add(res) ; } From 773fd559cdf313a52d04114604bf4ea4f0d752f4 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 17:36:41 +0200 Subject: [PATCH 17/64] [Positioning] Add ResultList::empty() --- owlps-positioning/src/resultlist.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/owlps-positioning/src/resultlist.hh b/owlps-positioning/src/resultlist.hh index 8159f6d..ee20901 100644 --- a/owlps-positioning/src/resultlist.hh +++ b/owlps-positioning/src/resultlist.hh @@ -25,6 +25,8 @@ public: /** @name Read accessors */ //@{ + /// Checks if there is at least one Result in the list + bool empty(void) const ; const Request* get_request(void) const ; const std::vector& get_results(void) const ; //@} @@ -57,6 +59,12 @@ public: /* *** Read accessors *** */ +inline bool ResultList::empty() const +{ + return results.empty() ; +} + + inline const Request* ResultList::get_request() const { return request ; From 948bd577a2585b0b2d21a2b0377d1293fbb86fe5 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 29 Jun 2011 17:36:59 +0200 Subject: [PATCH 18/64] [Positioning] Output*: do not output empty RequestList --- owlps-positioning/src/outputcsv.cc | 3 ++- owlps-positioning/src/outputterminal.cc | 5 ++++- owlps-positioning/src/outputudpsocket.cc | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/owlps-positioning/src/outputcsv.cc b/owlps-positioning/src/outputcsv.cc index 3347963..6acaf03 100644 --- a/owlps-positioning/src/outputcsv.cc +++ b/owlps-positioning/src/outputcsv.cc @@ -11,5 +11,6 @@ void OutputCSV::write(const Result &result) void OutputCSV::write(const ResultList &results) { - file.write_text(results.to_csv() + '\n') ; + if (! results.empty()) + file.write_text(results.to_csv() + '\n') ; } diff --git a/owlps-positioning/src/outputterminal.cc b/owlps-positioning/src/outputterminal.cc index 088366a..6736ef0 100644 --- a/owlps-positioning/src/outputterminal.cc +++ b/owlps-positioning/src/outputterminal.cc @@ -12,5 +12,8 @@ void OutputTerminal::write(const Result &result) void OutputTerminal::write(const ResultList &results) { - output_stream << results << '\n' ; + if (results.empty()) + output_stream << "There is no result.\n" ; + else + output_stream << results << '\n' ; } diff --git a/owlps-positioning/src/outputudpsocket.cc b/owlps-positioning/src/outputudpsocket.cc index 7f4cca1..4e4bc02 100644 --- a/owlps-positioning/src/outputudpsocket.cc +++ b/owlps-positioning/src/outputudpsocket.cc @@ -80,7 +80,8 @@ void OutputUDPSocket::write(const Result &result) void OutputUDPSocket::write(const ResultList &results) { - send_data(results.to_csv()) ; + if (! results.empty()) + send_data(results.to_csv()) ; } From 855291b31d4a1d12a0f1a6bc7f45b7c49568ff2d Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 13 Jul 2011 14:56:06 +0200 Subject: [PATCH 19/64] [Positioning] Add PosUtil::rad2deg() --- owlps-positioning/src/posutil.cc | 12 ++++++++++++ owlps-positioning/src/posutil.hh | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/owlps-positioning/src/posutil.cc b/owlps-positioning/src/posutil.cc index d1e36b7..78db584 100644 --- a/owlps-positioning/src/posutil.cc +++ b/owlps-positioning/src/posutil.cc @@ -5,11 +5,23 @@ #include +#include + using namespace std ; using std::tr1::unordered_map ; +/* *** Maths *** */ + + +double PosUtil::rad2deg(const double &radians) +{ + return radians * (180.0 / M_PI) ; +} + + + /* *** Measurements *** */ diff --git a/owlps-positioning/src/posutil.hh b/owlps-positioning/src/posutil.hh index 8e56ebb..ef1c64b 100644 --- a/owlps-positioning/src/posutil.hh +++ b/owlps-positioning/src/posutil.hh @@ -13,6 +13,12 @@ public: /// The speed of light, in m/s static const unsigned long LIGHT_SPEED = 299792458 ; + /** @name Maths */ + //@{ + /// Return the degree value of \em radians + static double rad2deg(const double &radians) ; + //@} + /** @name Measurements */ //@{ /// Mutually completes two Measurement lists with missing APs From f418fc15f1e75aed83139edb5a220769b5af43d2 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 13 Jul 2011 15:00:54 +0200 Subject: [PATCH 20/64] [Positioning] Add Point3D::angle() --- owlps-positioning/Makefile | 1 + owlps-positioning/src/point3d.cc | 21 +++++++++++++++++++++ owlps-positioning/src/point3d.hh | 4 +++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index aa875cf..b508a0b 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -139,6 +139,7 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cc $(SRC_DIR)/%.hh # Dependencies $(OBJ_DIR)/point3d.o: \ + $(OBJ_DIR)/posutil.o \ $(OBJ_DIR)/posexcept.o $(OBJ_DIR)/posutil.o: \ $(OBJ_DIR)/stock.o \ diff --git a/owlps-positioning/src/point3d.cc b/owlps-positioning/src/point3d.cc index 00d3606..bfc55f6 100644 --- a/owlps-positioning/src/point3d.cc +++ b/owlps-positioning/src/point3d.cc @@ -1,4 +1,5 @@ #include "point3d.hh" +#include "posutil.hh" #include "posexcept.hh" #include @@ -61,6 +62,26 @@ float Point3D::square_distance(const float _x, } +/** + * A, B and C are three points, A being the current Point3D (*this). + * @return The angle BÂC. + */ +double Point3D::angle(const Point3D &b, const Point3D &c) const +{ + float + sq_ab = square_distance(b), + ab = sqrt(sq_ab), + sq_ac = square_distance(c), + ac = sqrt(sq_ac), + sq_bc = b.square_distance(c) ; + + double cos_bac = (sq_ab + sq_ac - sq_bc) / (2 * ab * ac) ; + double bac = acos(cos_bac) ; + + return PosUtil::rad2deg(bac) ; +} + + /* *** Operators *** */ diff --git a/owlps-positioning/src/point3d.hh b/owlps-positioning/src/point3d.hh index 96300ab..54c536d 100644 --- a/owlps-positioning/src/point3d.hh +++ b/owlps-positioning/src/point3d.hh @@ -44,7 +44,7 @@ public: void set_coordinates(const Point3D &source) ; //@} - /** @name Distance operations */ + /** @name Distance & angles operations */ //@{ /// Square euclidean distance to a Point3D float square_distance(const Point3D &p) const ; @@ -61,6 +61,8 @@ public: /// Euclidean distance to the radius of a sphere float distance_to_sphere(const Point3D ¢re, const float radius) const ; + /// Angle BÂC (A being *this) + double angle(const Point3D &b, const Point3D &c) const ; //@} /** @name Operators */ From 33b027d47273c7386893dba35650963d39812d88 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 15 Jul 2011 18:26:16 +0200 Subject: [PATCH 21/64] [Positioning] Tweak ReferencePoint::friis_indexes_for_ap() --- owlps-positioning/src/referencepoint.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index c55babe..7112c9b 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -191,6 +191,7 @@ float ReferencePoint::friis_indexes_for_ap( double friis_idx_sum = 0 ; const string &ap_mac = ap.get_mac_addr() ; + float distance = this->distance(ap.get_coordinates()) ; /* * Compute an index for each Measurement in each Request in the @@ -206,7 +207,6 @@ float ReferencePoint::friis_indexes_for_ap( 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() ; From f5a4f4fedc9f073abc06eb74f0a1a0132983d989 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 18 Jul 2011 13:35:02 +0200 Subject: [PATCH 22/64] [Positioning] Point3D: fix angle() Use doubles instead of floats. Handle the cases where points are equal. --- owlps-positioning/src/point3d.cc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/owlps-positioning/src/point3d.cc b/owlps-positioning/src/point3d.cc index bfc55f6..10c7652 100644 --- a/owlps-positioning/src/point3d.cc +++ b/owlps-positioning/src/point3d.cc @@ -64,17 +64,24 @@ float Point3D::square_distance(const float _x, /** * A, B and C are three points, A being the current Point3D (*this). - * @return The angle BÂC. + * If the points are aligned, the angle returned is always 0° (and not + * 180°, even in the case where A is on BC). + * @returns The angle BÂC, in the interval [0, 180] degrees. */ double Point3D::angle(const Point3D &b, const Point3D &c) const { - float + double sq_ab = square_distance(b), - ab = sqrt(sq_ab), sq_ac = square_distance(c), - ac = sqrt(sq_ac), sq_bc = b.square_distance(c) ; + if (sq_ab == 0 || sq_ac == 0 || sq_bc == 0) + return 0 ; + + double + ab = sqrt(sq_ab), + ac = sqrt(sq_ac) ; + double cos_bac = (sq_ab + sq_ac - sq_bc) / (2 * ab * ac) ; double bac = acos(cos_bac) ; From d9bfd9e2c28f2f10588c5b949572340e00265dff Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 18:00:36 +0200 Subject: [PATCH 23/64] [Positioning] AccessPointsReaderCSV: s/ap/device/ --- owlps-positioning/src/accesspointsreadercsv.cc | 12 ++++++------ owlps-positioning/src/accesspointsreadercsv.hh | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/owlps-positioning/src/accesspointsreadercsv.cc b/owlps-positioning/src/accesspointsreadercsv.cc index 858b9a3..93ccb07 100644 --- a/owlps-positioning/src/accesspointsreadercsv.cc +++ b/owlps-positioning/src/accesspointsreadercsv.cc @@ -13,7 +13,7 @@ using namespace std ; AccessPointsReaderCSV::AccessPointsReaderCSV(const string &file_name): file(file_name) { - read_access_points() ; + read_devices() ; } @@ -21,14 +21,14 @@ AccessPointsReaderCSV::AccessPointsReaderCSV(const string &file_name): /* *** Operations *** */ -void AccessPointsReaderCSV::read_access_points() +void AccessPointsReaderCSV::read_devices() { while (file.next_line()) - process_access_point_line() ; + process_device_line() ; } -void AccessPointsReaderCSV::process_access_point_line() +void AccessPointsReaderCSV::process_device_line() { string mac ; if (! file.read_field(mac)) @@ -53,6 +53,6 @@ void AccessPointsReaderCSV::process_access_point_line() string ip("") ; - AccessPoint ap(coord, ip, mac, gain, power, frequency) ; - Stock::find_create_ap(ap) ; + AccessPoint device(coord, ip, mac, gain, power, frequency) ; + Stock::find_create_ap(device) ; } diff --git a/owlps-positioning/src/accesspointsreadercsv.hh b/owlps-positioning/src/accesspointsreadercsv.hh index 97d8191..a81b7a4 100644 --- a/owlps-positioning/src/accesspointsreadercsv.hh +++ b/owlps-positioning/src/accesspointsreadercsv.hh @@ -17,8 +17,8 @@ class AccessPointsReaderCSV protected: CSVFileReader file ; - void read_access_points(void) ; - void process_access_point_line(void) ; + void read_devices(void) ; + void process_device_line(void) ; public: AccessPointsReaderCSV(const std::string &file_name) ; From b04cd1cdb87c9949acf4de7237219244fddee8ae Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 18:20:20 +0200 Subject: [PATCH 24/64] [Positioning] Add Stock::find_create_mobile(Mobile&) --- owlps-positioning/src/stock.cc | 15 +++++++++++++++ owlps-positioning/src/stock.hh | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index dee9a44..51a15bf 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -148,6 +148,21 @@ const Mobile& Stock::find_create_mobile(const string &mac) } +/** + * If the Mobile already exists, it is replaced by the \em source. + */ +const Mobile& Stock::find_create_mobile(const Mobile &source) +{ + const string &mac = source.get_mac_addr() ; + unordered_map::const_iterator i = mobiles.find(mac) ; + if (i != mobiles.end()) + return i->second ; + + mobiles[mac] = source ; + return mobiles[mac] ; +} + + /* *** AccessPoint operations *** */ diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index ab4cbab..db58fd3 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -70,8 +70,11 @@ public: //@{ /// Reads the Mobile corresponding to a given MAC address static const Mobile& get_mobile(const std::string &mac) ; - /// Searches for a Mobile and creates it if it does not exist + /// \brief Searches for a Mobile given its MAC address and creates + /// it if it does not exist static const Mobile& find_create_mobile(const std::string &mac) ; + /// Searches for a Mobile and create it if it does not exist + static const Mobile& find_create_mobile(const Mobile &source) ; /// \brief Returns a reference to the Mobile corresponding to a /// given MAC address static Mobile& getw_mobile(const std::string &mac) ; From 8878bb2390beaf04bc66e400b96eae4dc6337300 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 18:43:54 +0200 Subject: [PATCH 25/64] [Positioning] Add Stock::nb_mobiles() --- owlps-positioning/src/stock.hh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index db58fd3..ed540b5 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -68,6 +68,8 @@ public: /** @name Mobile operations */ //@{ + /// Returns the number of mobiles + static unsigned int nb_mobiles(void) ; /// Reads the Mobile corresponding to a given MAC address static const Mobile& get_mobile(const std::string &mac) ; /// \brief Searches for a Mobile given its MAC address and creates @@ -178,6 +180,12 @@ find_create_waypoint(const Waypoint &point) /* *** Mobile operations *** */ +inline unsigned int Stock::nb_mobiles() +{ + return mobiles.size() ; +} + + /** * If the Mobile corresponding to \em mac does not exist, it is created. * @param mac The MAC address of the Mobile to search for. It must be a From 0b43e7f5fcb614a7f5694c1a68b24e3dcc643c56 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 18:40:17 +0200 Subject: [PATCH 26/64] [Positioning] Read mobiles characteristics Add MobilesReaderCSV, that reads the known mobiles from a CSV file. --- owlps-positioning/Makefile | 6 +++ owlps-positioning/cfg/mobiles.csv | 10 +++++ owlps-positioning/cfg/owlps-positioning.cfg | 4 ++ owlps-positioning/src/inputdatareader.cc | 47 +++++++++++++++++++ owlps-positioning/src/inputdatareader.hh | 4 ++ owlps-positioning/src/mobilesreadercsv.cc | 50 +++++++++++++++++++++ owlps-positioning/src/mobilesreadercsv.hh | 29 ++++++++++++ owlps-positioning/src/userinterface.cc | 7 +++ 8 files changed, 157 insertions(+) create mode 100644 owlps-positioning/cfg/mobiles.csv create mode 100644 owlps-positioning/src/mobilesreadercsv.cc create mode 100644 owlps-positioning/src/mobilesreadercsv.hh diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index b508a0b..5c17b54 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -82,6 +82,7 @@ OBJ_LIST = \ userinterface.o \ inputdatareader.o \ accesspointsreadercsv.o \ + mobilesreadercsv.o \ topologyreadercsv.o \ textfilereader.o \ csvfilereader.o \ @@ -155,6 +156,7 @@ $(OBJ_DIR)/userinterface.o: \ $(OBJ_DIR)/configuration.o $(OBJ_DIR)/inputdatareader.o: \ $(OBJ_DIR)/accesspointsreadercsv.o \ + $(OBJ_DIR)/mobilesreadercsv.o \ $(OBJ_DIR)/topologyreadercsv.o \ $(OBJ_DIR)/configuration.o \ $(OBJ_DIR)/posexcept.o @@ -162,6 +164,10 @@ $(OBJ_DIR)/accesspointsreadercsv.o: \ $(OBJ_DIR)/csvfilereader.o \ $(OBJ_DIR)/accesspoint.o \ $(OBJ_DIR)/stock.o +$(OBJ_DIR)/mobilesreadercsv.o: \ + $(OBJ_DIR)/csvfilereader.o \ + $(OBJ_DIR)/mobile.o \ + $(OBJ_DIR)/stock.o $(OBJ_DIR)/topologyreadercsv.o: \ $(OBJ_DIR)/csvfilereader.o \ $(OBJ_DIR)/area.o \ diff --git a/owlps-positioning/cfg/mobiles.csv b/owlps-positioning/cfg/mobiles.csv new file mode 100644 index 0000000..69bc168 --- /dev/null +++ b/owlps-positioning/cfg/mobiles.csv @@ -0,0 +1,10 @@ +# Mobiles' physical description file. +# +# Each line follows this format: +# MAC address;Antenna gain (dBi);Trx power (dBm) +# +# Blank lines are ignored. Commented lines must have a sharp (#) as +# their FIRST character. + +# Example mobile: +#aa:bb:cc:dd:ee:ff;1.8;18.0 diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index b45091d..bbbcc24 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -10,6 +10,10 @@ ap-medium = CSV ap-csv-file = cfg/listeners.csv +# Description of the clients +mobile-medium = CSV +mobile-csv-file = cfg/mobiles.csv + # Description of deployment area topology. # You probably don't need a full description of the topology, see the # topology example file for details. diff --git a/owlps-positioning/src/inputdatareader.cc b/owlps-positioning/src/inputdatareader.cc index 0c4c9c3..637286f 100644 --- a/owlps-positioning/src/inputdatareader.cc +++ b/owlps-positioning/src/inputdatareader.cc @@ -1,5 +1,6 @@ #include "inputdatareader.hh" #include "accesspointsreadercsv.hh" +#include "mobilesreadercsv.hh" #include "topologyreadercsv.hh" #include "inputcsv.hh" #include "calibrationrequest.hh" @@ -19,6 +20,7 @@ using namespace std ; InputDataReader::InputDataReader() { read_access_points() ; + read_mobiles() ; read_topology() ; read_reference_points() ; } @@ -80,6 +82,51 @@ void InputDataReader::initialise_access_points_csv() +/* *** Mobiles *** */ + + +void InputDataReader::read_mobiles() +{ + if (! Configuration::is_configured("data-input.mobile-medium")) + return ; + + initialise_mobiles_media() ; + + if (Configuration::is_configured("verbose")) + cerr << Stock::nb_mobiles() << " mobiles stored.\n" ; +} + + +void InputDataReader::initialise_mobiles_media() +{ + const vector &media_names = + Configuration::string_vector_value("data-input.mobile-medium") ; + + for (vector::const_iterator i = media_names.begin() ; + i != media_names.end() ; ++i) + { + if (*i == "CSV") + initialise_mobiles_csv() ; + + else + throw bad_configuration( + "Mobiles' input medium type unknown « "+ *i +" »") ; + } +} + + +void InputDataReader::initialise_mobiles_csv() +{ + if (! Configuration::is_configured("data-input.mobile-csv-file")) + throw missing_configuration( + "No input CSV file specified for mobiles") ; + + MobilesReaderCSV( + Configuration::string_value("data-input.mobile-csv-file")) ; +} + + + /* *** Topology *** */ diff --git a/owlps-positioning/src/inputdatareader.hh b/owlps-positioning/src/inputdatareader.hh index 1808679..6af1b00 100644 --- a/owlps-positioning/src/inputdatareader.hh +++ b/owlps-positioning/src/inputdatareader.hh @@ -16,6 +16,10 @@ protected: void initialise_access_points_media(void) ; void initialise_access_points_csv(void) ; + void read_mobiles(void) ; + void initialise_mobiles_media(void) ; + void initialise_mobiles_csv(void) ; + void read_topology(void) ; void initialise_topology_media(void) ; void initialise_topology_csv(void) ; diff --git a/owlps-positioning/src/mobilesreadercsv.cc b/owlps-positioning/src/mobilesreadercsv.cc new file mode 100644 index 0000000..f628df3 --- /dev/null +++ b/owlps-positioning/src/mobilesreadercsv.cc @@ -0,0 +1,50 @@ +#include "mobilesreadercsv.hh" +#include "point3d.hh" +#include "stock.hh" +#include "posexcept.hh" + +using namespace std ; + + + +/* *** Constructors *** */ + + +MobilesReaderCSV::MobilesReaderCSV(const string &file_name): + file(file_name) +{ + read_devices() ; +} + + + +/* *** Operations *** */ + + +void MobilesReaderCSV::read_devices() +{ + while (file.next_line()) + process_device_line() ; +} + + +void MobilesReaderCSV::process_device_line() +{ + string mac ; + if (! file.read_field(mac)) + throw malformed_input_data("Cannot read mobile's MAC address!") ; + PosUtil::to_upper(mac) ; + + float gain ; + if (! file.read_field(gain)) + throw malformed_input_data("Cannot read mobile's gain!") ; + + float power ; + if (! file.read_field(power)) + throw malformed_input_data("Cannot read mobile's power!") ; + + string ip("") ; + + Mobile device(ip, mac, gain, power) ; + Stock::find_create_mobile(device) ; +} diff --git a/owlps-positioning/src/mobilesreadercsv.hh b/owlps-positioning/src/mobilesreadercsv.hh new file mode 100644 index 0000000..50e2324 --- /dev/null +++ b/owlps-positioning/src/mobilesreadercsv.hh @@ -0,0 +1,29 @@ +#ifndef _OWLPS_POSITIONING_MOBILESREADERCSV_HH_ +#define _OWLPS_POSITIONING_MOBILESREADERCSV_HH_ + +class Point3D ; + +#include "csvfilereader.hh" + +#include + +/// Reads and registers to the Stock Mobile list from CSV files +/** + * CSV format for access points is: + * MAC;Antenna_gain_dBi;Trx_power_dBm + */ +class MobilesReaderCSV +{ +protected: + CSVFileReader file ; + + void read_devices(void) ; + void process_device_line(void) ; + +public: + MobilesReaderCSV(const std::string &file_name) ; + + ~MobilesReaderCSV(void) {} +} ; + +#endif // _OWLPS_POSITIONING_MOBILESREADERCSV_HH_ diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 0353477..23d144a 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -106,6 +106,13 @@ void UserInterface::fill_data_input_options() ("data-input.ap-csv-file", po::value(), "CSV file to use for access points input (when" " data-input.ap-medium = CSV).") + ("data-input.mobile-medium", po::value< vector >() + ->composing(), + "Medium from which mobiles are read. You can specify this" + " option more than once. Allowed: CSV.") + ("data-input.mobile-csv-file", po::value(), + "CSV file to use for mobiles input (when" + " data-input.mobile-medium = CSV).") ("data-input.topology-medium,T", po::value< vector >() ->composing(), "Medium from which topology (buildings, areas and waypoints) is" From 6b662a597ae5a58accb8c2e47d504c9bd5ad6881 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 19:08:50 +0200 Subject: [PATCH 27/64] [Positioning] Add Stock::mobile_exists() --- owlps-positioning/src/stock.cc | 13 +++++++++++++ owlps-positioning/src/stock.hh | 2 ++ 2 files changed, 15 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 51a15bf..e16a50c 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -116,6 +116,19 @@ void Stock::waypoint_remove_building(const Waypoint &point, /* *** 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 \em true if a mobile with this MAC address exists. + * @return \em false if this MAC address was not found. + */ +bool Stock::mobile_exists(const std::string &mac) +{ + unordered_map::const_iterator i = mobiles.find(mac) ; + return i != mobiles.end() ; +} + + /** * @param mac The MAC address of the Mobile to search for. * It must be a valid MAC address, as no check is performed. diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index ed540b5..245bf59 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -70,6 +70,8 @@ public: //@{ /// Returns the number of mobiles static unsigned int nb_mobiles(void) ; + /// Verify the existence of a mobile + static bool mobile_exists(const std::string &mac) ; /// Reads the Mobile corresponding to a given MAC address static const Mobile& get_mobile(const std::string &mac) ; /// \brief Searches for a Mobile given its MAC address and creates From 9c76d87b0c0efb97fb32920733fb5b60d4493ad6 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Tue, 19 Jul 2011 19:05:38 +0200 Subject: [PATCH 28/64] [Positioning] Add option accept-new-mobiles The option positioning.accept-new-mobiles allows the program to add on-line mobiles that are not declared in the mobiles' configuration file. This was the default till now; now this option is unactivated by default to avoid unexpected Wi-Fi devices retransmitting positioning requests. --- owlps-positioning/cfg/owlps-positioning.cfg | 7 +++++++ owlps-positioning/src/inputcsv.cc | 5 +++++ owlps-positioning/src/inputudpsocket.cc | 5 +++++ owlps-positioning/src/userinterface.cc | 4 ++++ 4 files changed, 21 insertions(+) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index bbbcc24..294a580 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -79,6 +79,13 @@ csv-file = /tmp/owlps-positioning.log # It is unactivated by default for the sake of security. #accept-new-aps = false +# This option allows to create a new mobile when a request is sent by +# a mobile which is not currently in the mobiles' list (i.e. not +# declared in the mobiles' configuration file). If unset, the requests +# sent by unknown mobiles will be dropped. +# It is unactivated by default, mainly to avoid interferent devices. +#accept-new-mobiles = false + # When receiving a calibration or autocalibration request from an AP, # containing the transmiter's coordinates, memorise the new AP's # coordinates. diff --git a/owlps-positioning/src/inputcsv.cc b/owlps-positioning/src/inputcsv.cc index 47764fe..c4e8d8a 100644 --- a/owlps-positioning/src/inputcsv.cc +++ b/owlps-positioning/src/inputcsv.cc @@ -46,6 +46,11 @@ const Request& InputCSV::get_next_request() return *current_request ; } PosUtil::to_upper(mac_mobile) ; + + if (! Configuration::bool_value("positioning.accept-new-mobiles") && + ! Stock::mobile_exists(mac_mobile)) + return *current_request ; + const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ; current_request->set_mobile(&mobile) ; diff --git a/owlps-positioning/src/inputudpsocket.cc b/owlps-positioning/src/inputudpsocket.cc index b63f1e5..dafe816 100644 --- a/owlps-positioning/src/inputudpsocket.cc +++ b/owlps-positioning/src/inputudpsocket.cc @@ -110,6 +110,11 @@ const Request& InputUDPSocket::get_next_request() string mac_mobile( owl_mac_bytes_to_string(request.mobile_mac_addr_bytes)) ; PosUtil::to_upper(mac_mobile) ; + + if (! Configuration::bool_value("positioning.accept-new-mobiles") && + ! Stock::mobile_exists(mac_mobile)) + return *current_request ; + const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ; current_request->set_mobile(&mobile) ; diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 23d144a..377d9cd 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -210,6 +210,10 @@ void UserInterface::fill_positioning_options() "Allow AP's coordinates to be updated when a calibration request" " with new coordinates is received from the AP (default is false," " for security purposes).") + ("positioning.accept-new-mobiles", + po::value()->default_value(false), + "When receiving requests, add unknown mobiles (mobiles which are not" + " declared in the mobiles' configuration file) to the mobiles' list.") ; file_options->add(options) ; From a2a289f6519583a004b44b3ad99b176d0969be4f Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Wed, 20 Jul 2011 17:35:22 +0200 Subject: [PATCH 29/64] [Positioning] Debug checks for CR deletion Add asserts and debug messages in ReferencePoint::delete_requests() and Stock::delete_calibration_request(). --- owlps-positioning/src/referencepoint.cc | 7 +++++++ owlps-positioning/src/stock.cc | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index 7112c9b..f58f91f 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -113,10 +113,17 @@ get_requests(const string &mac_transmitter) const */ void ReferencePoint::delete_requests() { +#ifndef NDEBUG + int stock_nb_requests = Stock::nb_calibration_requests() ; +#endif // NDEBUG + for (vector::iterator i = requests.begin() ; i != requests.end() ; ++i) Stock::delete_calibration_request(**i) ; + assert(Stock::nb_calibration_requests() == + stock_nb_requests - requests.size()) ; + requests.clear() ; } diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index e16a50c..b8ac069 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -374,6 +374,18 @@ store_calibration_request(const CalibrationRequest &request) void Stock:: delete_calibration_request(const CalibrationRequest &request) { +#ifndef NDEBUG + unordered_set::const_iterator found = + calibration_requests.find(request) ; + if (found == calibration_requests.end()) + { + cerr + << "Error! Cannot delete an unstored CalibrationRequest: " + << request << endl ; + return ; + } +#endif // NDEBUG + calibration_requests.erase(request) ; } From 1abe54b7be481e5b0bdc5b6ecb252c37ed41cc2e Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 21 Jul 2011 14:37:19 +0200 Subject: [PATCH 30/64] [Positioning] Add PosUtil::int_to_mac() --- owlps-positioning/src/posutil.cc | 18 ++++++++++++++++++ owlps-positioning/src/posutil.hh | 1 + 2 files changed, 19 insertions(+) diff --git a/owlps-positioning/src/posutil.cc b/owlps-positioning/src/posutil.cc index 78db584..b88e8da 100644 --- a/owlps-positioning/src/posutil.cc +++ b/owlps-positioning/src/posutil.cc @@ -163,3 +163,21 @@ unsigned long PosUtil::wifi_channel_to_hz(const unsigned long &channel) // Error: wrong channel value throw bad_channel(channel) ; } + + + +/* *** Strings *** */ + + +string PosUtil::int_to_mac(const uint32_t source) +{ + uint8_t bytes[6] ; + memset(bytes, 0, 6) ; + for (int i = 0 ; i < 4 ; ++i) + bytes[i+2] = reinterpret_cast(&source)[i] ; + char mac_cstr[OWL_ETHER_ADDR_STRLEN] ; + owl_mac_bytes_to_string_r(bytes, mac_cstr) ; + string mac(mac_cstr) ; + to_upper(mac) ; + return mac ; +} diff --git a/owlps-positioning/src/posutil.hh b/owlps-positioning/src/posutil.hh index ef1c64b..0a5cb7f 100644 --- a/owlps-positioning/src/posutil.hh +++ b/owlps-positioning/src/posutil.hh @@ -41,6 +41,7 @@ public: //@{ static void to_upper(std::string &str) ; static void assert_uppercase(const std::string &str) ; + static std::string int_to_mac(const uint32_t source) ; //@} } ; From d1b575c95ea8a1f0ca9b99633e71563cd97488cc Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 21 Jul 2011 14:38:21 +0200 Subject: [PATCH 31/64] [Positioning] Add Stock::nb_virtual_mobiles --- owlps-positioning/src/stock.cc | 2 ++ owlps-positioning/src/stock.hh | 3 +++ 2 files changed, 5 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index b8ac069..cd7b6f6 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -16,6 +16,8 @@ unordered_map Stock::waypoints ; unordered_map Stock::mobiles ; +uint32_t Stock::nb_virtual_mobiles = 0 ; + unordered_map Stock::aps ; unordered_set mobiles ; + /// Number of generated "virtual" mobiles + static uint32_t nb_virtual_mobiles ; + /// List of known AccessPoint /** The string key of the map is the AccessPoint MAC address. */ static std::tr1::unordered_map aps ; From 6c48bc7e295163c2b506e36f7d77a6e5b5c5988d Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 21 Jul 2011 21:44:28 +0200 Subject: [PATCH 32/64] [Positioning] Add Stock::get_aps() --- owlps-positioning/src/stock.hh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 57e6ea1..3562083 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -91,6 +91,9 @@ public: //@{ /// Returns the number of access points static unsigned int nb_aps(void) ; + /// Returns a reference to the AP list + static + std::tr1::unordered_map& get_aps(void) ; /// Verify the existence of an AP static bool ap_exists(const std::string &mac) ; /// Reads the AccessPoint corresponding to a given MAC address @@ -213,6 +216,13 @@ inline unsigned int Stock::nb_aps() } +inline +std::tr1::unordered_map& Stock::get_aps() +{ + return aps ; +} + + /** * If the AccessPoint corresponding to \em mac does not exist, it is * created. From 232551c15012c46ed7182a4bda7152955c05cbc9 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 21 Jul 2011 21:39:54 +0200 Subject: [PATCH 33/64] [Positioning] ReferencePoint::delete_generated_requests() --- owlps-positioning/src/referencepoint.cc | 46 +++++++++++++++++++++++-- owlps-positioning/src/referencepoint.hh | 2 ++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index f58f91f..f769e42 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -117,9 +117,9 @@ void ReferencePoint::delete_requests() int stock_nb_requests = Stock::nb_calibration_requests() ; #endif // NDEBUG - for (vector::iterator i = requests.begin() ; - i != requests.end() ; ++i) - Stock::delete_calibration_request(**i) ; + for (vector::iterator r = requests.begin() ; + r != requests.end() ; ++r) + Stock::delete_calibration_request(**r) ; assert(Stock::nb_calibration_requests() == stock_nb_requests - requests.size()) ; @@ -128,6 +128,46 @@ void ReferencePoint::delete_requests() } +/** + * Note that the requests pointed by the elements of #requests are + * actually deleted from the Stock. + * @returns \em true if at least one request was deleted. + * @returns \em false if the ReferencePoint was left untouched. + */ +bool ReferencePoint::delete_generated_requests(void) +{ + bool modified = false ; + + for (vector::iterator r = requests.begin() ; + r != requests.end() ; ++r) + { + assert(*r) ; + if ((*r)->get_mobile() == NULL) + { + requests.erase(r) ; + modified = true ; + continue ; + } + + unordered_map::const_iterator ap ; + for (ap = Stock::get_aps().begin() ; ap != Stock::get_aps().end() ; + ++ap) + if ((*r)->get_mobile()->get_mac_addr() == + ap->second.get_mac_addr()) + break ; + + if (ap == Stock::get_aps().end()) // r is not associated with an AP + { + Stock::delete_calibration_request(**r) ; + requests.erase(r) ; + modified = true ; + } + } + + return modified ; +} + + /* *** Operations *** */ diff --git a/owlps-positioning/src/referencepoint.hh b/owlps-positioning/src/referencepoint.hh index efd26a8..4516cc1 100644 --- a/owlps-positioning/src/referencepoint.hh +++ b/owlps-positioning/src/referencepoint.hh @@ -57,6 +57,8 @@ public: void add_request(const CalibrationRequest *cm) ; /// Deletes all the requests contained in #requests void delete_requests(void) ; + /// Deletes the requests that are not sent by an AP + bool delete_generated_requests(void) ; //@} /** @name Operations */ From 2b12e493748bb4bb68b3a8440bb26d4dbd611f4e Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 22 Jul 2011 10:48:19 +0200 Subject: [PATCH 34/64] [Positioning] Fix ReferencePoint::delete_generated_requests() Use a while loop instead of for to check the requests. --- owlps-positioning/src/referencepoint.cc | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index f769e42..2966825 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -136,35 +136,35 @@ void ReferencePoint::delete_requests() */ bool ReferencePoint::delete_generated_requests(void) { - bool modified = false ; - - for (vector::iterator r = requests.begin() ; - r != requests.end() ; ++r) + unsigned int nb_requests = requests.size() ; + vector::iterator r = requests.begin() ; + while (r != requests.end()) { assert(*r) ; - if ((*r)->get_mobile() == NULL) - { - requests.erase(r) ; - modified = true ; - continue ; - } - unordered_map::const_iterator ap ; + + if ((*r)->get_mobile() == NULL) + goto delete_request ; + for (ap = Stock::get_aps().begin() ; ap != Stock::get_aps().end() ; ++ap) if ((*r)->get_mobile()->get_mac_addr() == ap->second.get_mac_addr()) break ; - if (ap == Stock::get_aps().end()) // r is not associated with an AP + if (ap != Stock::get_aps().end()) // r still associated with an AP { - Stock::delete_calibration_request(**r) ; - requests.erase(r) ; - modified = true ; + ++r ; + continue ; // Do not delete r } + + // r is not assotiated with an AP, delete it +delete_request: + Stock::delete_calibration_request(**r) ; + r = requests.erase(r) ; } - return modified ; + return nb_requests != requests.size() ; } From 3c00c3bb196375821fc51bd0eaa4fbc6c9a8eddd Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 21 Jul 2011 21:46:39 +0200 Subject: [PATCH 35/64] [lib] Add request type "generated" This new type of request will only be used in owlps-positioning, to distinct the calibration requests that are issued from a real measurement and those that are generated by the self-calibration process. --- libowlps/owlps.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libowlps/owlps.h b/libowlps/owlps.h index 70f4cf9..5a5cfd5 100644 --- a/libowlps/owlps.h +++ b/libowlps/owlps.h @@ -119,6 +119,7 @@ typedef struct _owl_autocalibration_order #define OWL_REQUEST_NORMAL 0 #define OWL_REQUEST_CALIBRATION 1 #define OWL_REQUEST_AUTOCALIBRATION 2 +#define OWL_REQUEST_GENERATED 3 #define OWL_REQUEST_IMPLICIT 10 #define OWL_REQUEST_UNDEFINED 255 From 0d160f8b23512087bb3bbfc7b793feeb491ad506 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 22 Jul 2011 11:29:30 +0200 Subject: [PATCH 36/64] [Positioning] Add option generate-reference-points The self-calibration is here! There is certainly some things to fix, but the big step is made. --- owlps-positioning/cfg/owlps-positioning.cfg | 4 + owlps-positioning/src/input.cc | 3 + owlps-positioning/src/stock.cc | 197 ++++++++++++++++++++ owlps-positioning/src/stock.hh | 3 + owlps-positioning/src/userinterface.cc | 4 + 5 files changed, 211 insertions(+) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index 294a580..3bbfcfa 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -63,6 +63,10 @@ csv-file = /tmp/owlps-positioning.log # request is compared directly to each calibration request. #radar-average-reference-points = false +# Generate reference points from the (auto)calibration requests +# received. +#generate-reference-points = false + # This option allows the calibration requests sent during the # positioning phase to be added to the calibration request's list. They # are added to the calibration requests read by InputDataReader during diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index e736ab3..58ad95f 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -130,6 +130,9 @@ const Request& Input::get_next_request() const { calibration_request->reference_point_delete_requests() ; Stock::store_calibration_request(*calibration_request) ; + if (Configuration:: + bool_value("positioning.generate-reference-points")) + Stock::regenerate_reference_points() ; } } } diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index cd7b6f6..e14002a 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -360,6 +360,203 @@ closest_reference_point(const Request &request) } +/** + * Each 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) and a receiver RX (the current AP). + * To generate the signal strength (SS) received in P 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::regenerate_reference_points() +{ + assert(! aps.empty()) ; + assert(! reference_points.empty()) ; + + /* Delete calibration requests that do not come from the APs */ + unordered_set::iterator rp = reference_points.begin() ; + while (rp != reference_points.end()) + { + ReferencePoint rp_copy(*rp) ; + if (rp_copy.delete_generated_requests()) // rp_copy was modified + { + rp = reference_points.erase(rp) ; + // Reinsert the modified copy if it still contains at least + // one CalibrationRequest: + if (! rp_copy.get_requests().empty()) + reference_points.insert(rp_copy) ; + /* __Note on the above insert__ + * From the boost::unordered documentation: + * "insert is only allowed to invalidate iterators when the + * insertion causes the load factor to be greater than or + * equal to the maximum load factor." + * In our case, we always remove an element prior to insert, + * so the load factor will never change; therefore insert() + * should be safe here. + */ + } + else // rp_copy was not modified + ++rp ; + } + + if (reference_points.size() < 3) + { + if (Configuration::is_configured("verbose")) + cerr + << reference_points.size() << " true reference points is" + << " not enough to generate reference points.\n" ; + return ; + } + + /* Generate RPs */ + if (! Configuration::is_configured("positioning.minmax-start") || + ! Configuration::is_configured("positioning.minmax-stop")) + throw missing_configuration( + "You must define the deployment area in order to generate" + " reference points.") ; + Point3D start( + Configuration::string_value("positioning.minmax-start")) ; + Point3D stop( + Configuration::string_value("positioning.minmax-stop")) ; + float step = 0.5 ; // FIXME + float z = 1 ; // FIXME + 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) + { + Point3D current_point(x,y,z) ; + + for (unordered_map::const_iterator + rx = aps.begin() ; rx != aps.end() ; ++rx) + { + /* Choose the 2 nearest APs in angle */ + const Point3D &rx_coord = + rx->second.get_coordinates() ; + multimap::const_iterator> + sorted_angles ; + for (unordered_map::const_iterator + ref = aps.begin() ; ref != aps.end() ; ++ref) + { + if (ref == rx) + continue ; + const Point3D &ref_coord = + ref->second.get_coordinates() ; + double angle = + rx_coord.angle(current_point, ref_coord) ; + pair::const_iterator> + angle_ap(angle, ref) ; + sorted_angles.insert(angle_ap) ; + } + assert(sorted_angles.size() > 1) ; + + /* Compute the angle weight of the 2 reference APs */ + map::const_iterator> + ::const_iterator s = sorted_angles.begin() ; + // Angle REF1-RX-P + double ref1_angle = s->first ; + const AccessPoint &ref1 = s->second->second ; + ++s ; + const AccessPoint &ref2 = s->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(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 + * distance of RX-P, in the direction of each reference AP */ + // Distance RX-P + float current_point_dst = + rx_coord.distance(current_point) ; + // Constants & common data + double wavelength = + static_cast(PosUtil::LIGHT_SPEED) / + rx->second.get_frequency() ; + double common_ss = + rx->second.get_antenna_gain() + + 20 * log10(wavelength) - + 20 * log10(4 * M_PI) ; + // SS for REF1 + const ReferencePoint &ref1_rp = + get_reference_point(ref1_coord) ; + double friis_index = + ref1_rp.friis_index_for_ap(rx->second.get_mac_addr()) ; + double ref1_ss = + common_ss + + ref1.get_trx_power() + + ref1.get_antenna_gain() - + 10 * friis_index * log10(current_point_dst) ; + // SS for REF2 + const ReferencePoint &ref2_rp = + get_reference_point(ref2_coord) ; + friis_index = + ref2_rp.friis_index_for_ap(rx->second.get_mac_addr()) ; + double ref2_ss = + common_ss + + ref2.get_trx_power() + + ref2.get_antenna_gain() - + 10 * friis_index * log10(current_point_dst) ; + + /* Compute the SS */ + ref1_ss = ref1_ss * ref1_percent / 100 ; + ref2_ss = ref2_ss * ref2_percent / 100 ; + double rx_ss = (ref1_ss + ref2_ss) / 2 ; + + /* Create the timestamp */ + Timestamp time_sent ; + time_sent.now() ; + + /* Create the virtual mobile */ + string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ; + float vmob_gain = + ref1.get_antenna_gain() * ref1_percent / 100 + + ref2.get_antenna_gain() * ref2_percent / 100 ; + float vmob_pow = + ref1.get_trx_power() * ref1_percent / 100 + + ref2.get_trx_power() * ref2_percent / 100 ; + Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ; + const Mobile &mobile = find_create_mobile(vmob) ; + + /* Create the measurement list */ + Measurement m(&rx->second) ; + m.add_ss(rx_ss) ; + unordered_map measurements ; + measurements[rx->second.get_mac_addr()] = m ; + + /* Get/create the reference point */ + const ReferencePoint &rp = + find_create_reference_point(current_point) ; + + /* 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(&rp) ; + store_calibration_request(cr) ; + } + } +} + + /* *** CalibrationRequest operations *** */ diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 3562083..dd8cb91 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -126,6 +126,9 @@ public: /// strength space) to a given Request static const ReferencePoint& closest_reference_point(const Request &request) ; + /// \brief Generates reference points from the reference points + /// corresponding to APs + static void regenerate_reference_points(void) ; //@} /** @name CalibrationRequest operations */ diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 377d9cd..a0be735 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -193,6 +193,10 @@ void UserInterface::fill_positioning_options() " before to compute the SS distance." " The default is false, i.e the positioning request is compared" " directly to each calibration request.") + ("positioning.generate-reference-points", + po::value()->default_value(false), + "Generate reference points from the (auto)calibration requests" + " received.") ("positioning.accept-new-calibration-requests", po::value()->default_value(false), "Add the calibration requests received during the run-time to" From 602f9c5399af44d1a112b95d908ce1204cce36e8 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 22 Jul 2011 10:04:32 +0200 Subject: [PATCH 37/64] [Positioning] ReferencePoint: variable renaming --- owlps-positioning/src/referencepoint.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/owlps-positioning/src/referencepoint.hh b/owlps-positioning/src/referencepoint.hh index 4516cc1..71ee8dd 100644 --- a/owlps-positioning/src/referencepoint.hh +++ b/owlps-positioning/src/referencepoint.hh @@ -54,7 +54,7 @@ public: /** @name Write accessors */ //@{ /// Adds a Request to the \link #requests request list\endlink - void add_request(const CalibrationRequest *cm) ; + void add_request(const CalibrationRequest *r) ; /// Deletes all the requests contained in #requests void delete_requests(void) ; /// Deletes the requests that are not sent by an AP @@ -104,16 +104,16 @@ std::vector& ReferencePoint::get_requests() const /** - * @param cm A pointer to the CalibrationRequest to add. If it is + * @param r A pointer to the CalibrationRequest to add. If it is * NULL, nothing will be done. * The memory pointed by this pointer must not be deallocated before * the ReferencePoint destruction (do \em not pass a pointer to a local * variable!). */ -inline void ReferencePoint::add_request(const CalibrationRequest *cm) +inline void ReferencePoint::add_request(const CalibrationRequest *r) { - if (cm != NULL) - requests.push_back(const_cast(cm)) ; + if (r != NULL) + requests.push_back(const_cast(r)) ; } From d03d2405688ba9ce551580d679beda78e23baa77 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 22 Jul 2011 11:17:40 +0200 Subject: [PATCH 38/64] [Positioning] ReferencePoint: add an assertion Add an assertion into friis_indexes_for_ap(). --- owlps-positioning/src/referencepoint.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/owlps-positioning/src/referencepoint.cc b/owlps-positioning/src/referencepoint.cc index 2966825..37abd58 100644 --- a/owlps-positioning/src/referencepoint.cc +++ b/owlps-positioning/src/referencepoint.cc @@ -255,6 +255,7 @@ float ReferencePoint::friis_indexes_for_ap( if (measurement != measurements.end()) { double ss = measurement->second.get_average_ss() ; + assert((*request)->get_mobile()) ; float mobile_gain = (*request)->get_mobile()->get_antenna_gain() ; friis_idx_sum += From a801eb84d18178940bb1377fc53b63147ea6163a Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 22 Jul 2011 12:04:58 +0200 Subject: [PATCH 39/64] [Positioning] Add Stock::is_ap_coordinate() --- owlps-positioning/src/stock.cc | 15 +++++++++++++++ owlps-positioning/src/stock.hh | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index e14002a..ce4a12e 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -300,6 +300,21 @@ double Stock::ap_matrix_get_ss(const std::string &mac_transmitter, } +/** + * @returns \em true if \em coord are the coordinates of an existing + * AP, \em false if not. + */ +bool Stock::is_ap_coordinate(const Point3D &coord) +{ + for (unordered_map::const_iterator ap = + aps.begin() ; ap != aps.end() ; ++ap) + if (ap->second.get_coordinates() == coord) + return true ; + + return false ; +} + + /* *** ReferencePoint operations *** */ diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index dd8cb91..fb8a50a 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -108,8 +108,12 @@ public: static AccessPoint& getw_ap(const std::string &mac) ; /// Updates the friis indexes of all the APs static void update_all_friis_indexes(void) ; + /// \brief Returns the signal strenth received by an AP mac_receiver + /// from an AP mac_transmitter static double ap_matrix_get_ss(const std::string &mac_transmitter, const std::string &mac_receiver) ; + /// Checks if a Point3D is the coordinate of an existing AP + static bool is_ap_coordinate(const Point3D &coord) ; //@} /** @name ReferencePoint operations */ From c85c6357fbef02e50a8d4f56e413f7e1cb1fe59d Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 09:07:51 +0200 Subject: [PATCH 40/64] [Positioning] Input::get_next_request(): refactor. --- owlps-positioning/src/input.cc | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index 58ad95f..ba36226 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -117,12 +117,11 @@ const Request& Input::get_next_request() const log_current_request() ; // If the request is a calibration request, add it to the Stock - // (if allowed) - if (Configuration:: - bool_value("positioning.accept-new-calibration-requests")) + // (if allowed, and if it is not empty) + if (Configuration::bool_value( + "positioning.accept-new-calibration-requests") + && request) { - if (! request) // Skip the request if empty - return request ; CalibrationRequest *calibration_request = dynamic_cast( const_cast(&request)) ; @@ -130,8 +129,8 @@ const Request& Input::get_next_request() const { calibration_request->reference_point_delete_requests() ; Stock::store_calibration_request(*calibration_request) ; - if (Configuration:: - bool_value("positioning.generate-reference-points")) + if (Configuration::bool_value( + "positioning.generate-reference-points")) Stock::regenerate_reference_points() ; } } From 3402809c09f95d1fac73a267d75e88a2108659a4 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 09:10:49 +0200 Subject: [PATCH 41/64] [Positioning] Stock: do not regenerate AP coord. Do not generate reference points where an AP sits (normally we already have the true measurement). --- owlps-positioning/src/stock.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index ce4a12e..194bde9 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -445,6 +445,11 @@ void Stock::regenerate_reference_points() { Point3D current_point(x,y,z) ; + // If the point is the coordinates of an existing AP, we don't + // need to generate it + if (is_ap_coordinate(current_point)) + continue ; + for (unordered_map::const_iterator rx = aps.begin() ; rx != aps.end() ; ++rx) { From 2ddad20371983d5f6ba95f404f120b4051e51a5c Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 09:13:22 +0200 Subject: [PATCH 42/64] [Positioning] Stock: generate one CR for all APs A Request is received by *all* the APs, therefore we have to generate one CalibrationRequest per ReferencePoint, and not one CalibrationRequest per AP in each ReferencePoint. --- owlps-positioning/src/stock.cc | 65 +++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 194bde9..2e8c88b 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -450,9 +450,31 @@ void Stock::regenerate_reference_points() if (is_ap_coordinate(current_point)) continue ; + /* Get/create the reference point */ + const ReferencePoint ¤t_rp = + find_create_reference_point(current_point) ; + + /* Create the timestamp */ + Timestamp time_sent ; + time_sent.now() ; + + /* Create the measurement list */ + unordered_map 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::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() ; + /* Choose the 2 nearest APs in angle */ const Point3D &rx_coord = rx->second.get_coordinates() ; @@ -540,39 +562,24 @@ void Stock::regenerate_reference_points() ref2_ss = ref2_ss * ref2_percent / 100 ; double rx_ss = (ref1_ss + ref2_ss) / 2 ; - /* Create the timestamp */ - Timestamp time_sent ; - time_sent.now() ; - - /* Create the virtual mobile */ - string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ; - float vmob_gain = - ref1.get_antenna_gain() * ref1_percent / 100 + - ref2.get_antenna_gain() * ref2_percent / 100 ; - float vmob_pow = - ref1.get_trx_power() * ref1_percent / 100 + - ref2.get_trx_power() * ref2_percent / 100 ; - Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ; - const Mobile &mobile = find_create_mobile(vmob) ; - - /* Create the measurement list */ + /* Create the measurement, add it to the list */ Measurement m(&rx->second) ; m.add_ss(rx_ss) ; - unordered_map measurements ; measurements[rx->second.get_mac_addr()] = m ; - - /* Get/create the reference point */ - const ReferencePoint &rp = - find_create_reference_point(current_point) ; - - /* 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(&rp) ; - store_calibration_request(cr) ; } + + /* 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) ; } } From ea81916937b7425f843806738bd8cbd0ec6265c3 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 11:44:04 +0200 Subject: [PATCH 43/64] [Positioning] Add option position-calibration-requests This option allows the calibration requests to be positioned as positioning requests. --- owlps-positioning/cfg/owlps-positioning.cfg | 7 +++++++ owlps-positioning/src/input.cc | 4 ++++ owlps-positioning/src/userinterface.cc | 6 ++++++ 3 files changed, 17 insertions(+) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index 3bbfcfa..e585c08 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -76,6 +76,13 @@ csv-file = /tmp/owlps-positioning.log # it is not activated by default for security purposes. #accept-new-calibration-requests = false +# If you activate the above option and want the calibration requests +# to be treated as positioning requests (in addition to the normal +# treatment of calibration requests), activate this option. +# The default is false: the first calibration requests' purpose is to +# serve the positioning process, not to use it. +#position-calibration-requests = false + # This option allows to create a new AP when a request is captured by an # AP which is not currently in the APs' list (i.e. not declared in the # APs' configuration file), or when a self-calibration request is sent diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index ba36226..7e452b7 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -132,6 +132,10 @@ const Request& Input::get_next_request() const if (Configuration::bool_value( "positioning.generate-reference-points")) Stock::regenerate_reference_points() ; + + if (! Configuration::bool_value( + "positioning.position-calibration-requests")) + medium->clear_current_request() ; } } } diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index a0be735..e5d7393 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -204,6 +204,12 @@ void UserInterface::fill_positioning_options() " self-calibration. If unactivated, the calibration requests" " are handled as positioning requests (default is unactivated," " for security purposes).") + ("positioning.position-calibration-requests", + po::value()->default_value(false), + "When accept-new-calibration-requests is activated, allow the" + " calibration requests to be positioned as normal requests." + " The default is to add them to the calibration requests' list" + " without position them.") ("positioning.accept-new-aps", po::value()->default_value(false), "When receiving requests, add unknown APs (APs which are not" From a975731ae41e9b52795c835661c44c3d3d1f5520 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 13:18:13 +0200 Subject: [PATCH 44/64] [Positioning] OutputTerminal: handle flush-output-files Flush the output stream when the option flush-output-files is activated. --- owlps-positioning/src/outputterminal.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/owlps-positioning/src/outputterminal.cc b/owlps-positioning/src/outputterminal.cc index 6736ef0..6473940 100644 --- a/owlps-positioning/src/outputterminal.cc +++ b/owlps-positioning/src/outputterminal.cc @@ -1,5 +1,6 @@ #include "outputterminal.hh" #include "resultlist.hh" +#include "configuration.hh" @@ -16,4 +17,6 @@ void OutputTerminal::write(const ResultList &results) output_stream << "There is no result.\n" ; else output_stream << results << '\n' ; + if (Configuration::bool_value("flush-output-files")) + output_stream << std::flush ; } From 26e3c33366130a9e5a17d3561cd2b6a96a7197fc Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 17:18:48 +0200 Subject: [PATCH 45/64] [Positioning] RP generation: fix SS weighting The weighted mean of the SSs for the selected APs was wrong (an extra division by 2) --- owlps-positioning/src/stock.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 2e8c88b..37944f7 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -560,7 +560,7 @@ void Stock::regenerate_reference_points() /* Compute the SS */ ref1_ss = ref1_ss * ref1_percent / 100 ; ref2_ss = ref2_ss * ref2_percent / 100 ; - double rx_ss = (ref1_ss + ref2_ss) / 2 ; + double rx_ss = ref1_ss + ref2_ss ; /* Create the measurement, add it to the list */ Measurement m(&rx->second) ; From d735df6f943a39bed2b2b88e4688fa7f1ac40311 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 17:52:07 +0200 Subject: [PATCH 46/64] [Positioning] Input: display the number of CR When receiving a new calibration request, display an info message (with verbose mode on). --- owlps-positioning/src/input.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index 7e452b7..4708947 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -129,6 +129,14 @@ const Request& Input::get_next_request() const { calibration_request->reference_point_delete_requests() ; Stock::store_calibration_request(*calibration_request) ; + + if (Configuration::is_configured("verbose")) + cerr + << "Got a new calibration request (total " + << Stock::nb_calibration_requests() << " in " + << Stock::nb_reference_points() + << " reference points).\n" ; + if (Configuration::bool_value( "positioning.generate-reference-points")) Stock::regenerate_reference_points() ; From 4c53ed372a162cadbdc9d110f63e98f52ddab370 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 18:09:58 +0200 Subject: [PATCH 47/64] [Positioning] Add Configuration::float_value() --- owlps-positioning/src/configuration.cc | 6 ++++++ owlps-positioning/src/configuration.hh | 2 ++ 2 files changed, 8 insertions(+) diff --git a/owlps-positioning/src/configuration.cc b/owlps-positioning/src/configuration.cc index 6f33334..67ad563 100644 --- a/owlps-positioning/src/configuration.cc +++ b/owlps-positioning/src/configuration.cc @@ -41,6 +41,12 @@ int Configuration::int_value(const string &key) } +float Configuration::float_value(const string &key) +{ + return configuration[key].as() ; +} + + bool Configuration::bool_value(const string &key) { return configuration[key].as() ; diff --git a/owlps-positioning/src/configuration.hh b/owlps-positioning/src/configuration.hh index 7f089b2..948618b 100644 --- a/owlps-positioning/src/configuration.hh +++ b/owlps-positioning/src/configuration.hh @@ -21,6 +21,8 @@ public: static const std::string& string_value(const std::string &key) ; /// Returns the int value corresponding to \em key static int int_value(const std::string &key) ; + /// Returns the float value corresponding to \em key + static float float_value(const std::string &key) ; /// Returns the bool value corresponding to \em key static bool bool_value(const std::string &key) ; /// Checks if a given string value exists in \em key From 9b245ce1527ba6155058b36203e343acda19a432 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sat, 23 Jul 2011 18:08:54 +0200 Subject: [PATCH 48/64] [Positioning] Add option generated-meshing-grain The option positioning.generated-meshing-grain allows to set the grain of the generated reference points' meshing. --- owlps-positioning/cfg/owlps-positioning.cfg | 4 ++++ owlps-positioning/src/stock.cc | 3 ++- owlps-positioning/src/userinterface.cc | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index e585c08..2a57570 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -67,6 +67,10 @@ csv-file = /tmp/owlps-positioning.log # received. #generate-reference-points = false +# When the above option is activated, the reference points are generated +# with the specified distance (in meters) between one another. +#generated-meshing-grain = 0.5 + # This option allows the calibration requests sent during the # positioning phase to be added to the calibration request's list. They # are added to the calibration requests read by InputDataReader during diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 37944f7..53cf043 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -437,7 +437,8 @@ void Stock::regenerate_reference_points() Configuration::string_value("positioning.minmax-start")) ; Point3D stop( Configuration::string_value("positioning.minmax-stop")) ; - float step = 0.5 ; // FIXME + float step = + Configuration::float_value("positioning.generated-meshing-grain") ; float z = 1 ; // FIXME for (float x = start.get_x() ; x <= stop.get_x() ; x += step) for (float y = start.get_y() ; y <= stop.get_y() ; y += step) diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index e5d7393..375a150 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -197,6 +197,10 @@ void UserInterface::fill_positioning_options() po::value()->default_value(false), "Generate reference points from the (auto)calibration requests" " received.") + ("positioning.generated-meshing-grain", + po::value()->default_value(0.5), + "When generating reference points, this distance (in meters) will" + " separate each point to the next.") ("positioning.accept-new-calibration-requests", po::value()->default_value(false), "Add the calibration requests received during the run-time to" From 3490b94df7168a524de5cfd0aaa6a7f9a44c5048 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 13:53:47 +0200 Subject: [PATCH 49/64] [Positioning] Building & CSVFileReader: minor edits Building: fix a comment. CSVFileReader: delete useless "boost::" prefix (we have using namespace boost). --- owlps-positioning/src/building.cc | 2 +- owlps-positioning/src/csvfilereader.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/owlps-positioning/src/building.cc b/owlps-positioning/src/building.cc index da68289..d2b8ec9 100644 --- a/owlps-positioning/src/building.cc +++ b/owlps-positioning/src/building.cc @@ -39,7 +39,7 @@ Building::~Building() /** - * @param area A pointer to the Area to add. If \em a is NULL, nothing + * @param area A pointer to the Area to add. If it is NULL, nothing * will be added. If the Area it points to already exist in #areas, it is * deleted and nullified, unless it is the same pointer (see the code to * understand!); hmm, maybe we should handle that with exceptions… diff --git a/owlps-positioning/src/csvfilereader.cc b/owlps-positioning/src/csvfilereader.cc index 17fced7..faad541 100644 --- a/owlps-positioning/src/csvfilereader.cc +++ b/owlps-positioning/src/csvfilereader.cc @@ -101,9 +101,9 @@ bool CSVFileReader::read_point3d(Point3D &p) try { - coord[i] = boost::lexical_cast(*token_iterator) ; + coord[i] = lexical_cast(*token_iterator) ; } - catch (boost::bad_lexical_cast &e) + catch (bad_lexical_cast &e) { print_error_cast() ; return false ; From d5fcfed1f28e83f89f9e5147c2ebbe2bc41a4334 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Thu, 14 Jul 2011 22:07:48 +0200 Subject: [PATCH 50/64] [Positioning] Add OutputTCPSocketEvAAL --- owlps-positioning/Makefile | 5 + owlps-positioning/src/output.cc | 34 ++-- owlps-positioning/src/output.hh | 1 + owlps-positioning/src/outputtcpsocketevaal.cc | 157 ++++++++++++++++++ owlps-positioning/src/outputtcpsocketevaal.hh | 51 ++++++ owlps-positioning/src/userinterface.cc | 5 +- 6 files changed, 239 insertions(+), 14 deletions(-) create mode 100644 owlps-positioning/src/outputtcpsocketevaal.cc create mode 100644 owlps-positioning/src/outputtcpsocketevaal.hh diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index 5c17b54..f720f45 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -91,6 +91,7 @@ OBJ_LIST = \ outputterminal.o \ outputcsv.o \ outputudpsocket.o \ + outputtcpsocketevaal.o \ positioning.o \ input.o \ inputcsv.o \ @@ -246,6 +247,9 @@ $(OBJ_DIR)/outputcsv.o: \ $(OBJ_DIR)/outputudpsocket.o: \ $(SRC_DIR)/outputmedium.hh \ $(OBJ_DIR)/result.o +$(OBJ_DIR)/outputtcpsocketevaal.o: \ + $(SRC_DIR)/outputmedium.hh \ + $(OBJ_DIR)/result.o $(OBJ_DIR)/outputcsv.o: \ $(SRC_DIR)/outputmedium.hh \ $(OBJ_DIR)/result.o @@ -253,6 +257,7 @@ $(OBJ_DIR)/output.o: \ $(OBJ_DIR)/outputterminal.o \ $(OBJ_DIR)/outputcsv.o \ $(OBJ_DIR)/outputudpsocket.o \ + $(OBJ_DIR)/outputtcpsocketevaal.o \ $(OBJ_DIR)/configuration.o \ $(OBJ_DIR)/posexcept.o $(OBJ_DIR)/multilaterationalgorithm.o: \ diff --git a/owlps-positioning/src/output.cc b/owlps-positioning/src/output.cc index 0496953..43cbee3 100644 --- a/owlps-positioning/src/output.cc +++ b/owlps-positioning/src/output.cc @@ -5,6 +5,7 @@ #include "outputterminal.hh" #include "outputcsv.hh" #include "outputudpsocket.hh" +#include "outputtcpsocketevaal.hh" #include @@ -57,6 +58,9 @@ void Output::initialise_output_media() else if (*i == "UDP") initialise_output_udp_socket() ; + else if (*i == "TCPEvAAL") + initialise_output_tcpevaal_socket() ; + else throw bad_configuration( "The specified output medium « "+ *i +" » is unknown!") ; @@ -70,18 +74,6 @@ void Output::initialise_output_terminal() } -void Output::initialise_output_udp_socket() -{ - if (! Configuration::is_configured("output.udp-host")) - throw missing_configuration( - "No remote UDP host specified in the configuration!") ; - - output_media.push_back( - new OutputUDPSocket(Configuration::string_value("output.udp-host"), - Configuration::int_value("output.udp-port"))) ; -} - - void Output::initialise_output_csv() { if (! Configuration::is_configured("output.csv-file")) @@ -94,6 +86,24 @@ void Output::initialise_output_csv() } +void Output::initialise_output_udp_socket() +{ + if (! Configuration::is_configured("output.udp-host")) + throw missing_configuration( + "No remote UDP host specified in the configuration!") ; + + output_media.push_back( + new OutputUDPSocket(Configuration::string_value("output.udp-host"), + Configuration::int_value("output.udp-port"))) ; +} + + +void Output::initialise_output_tcpevaal_socket() +{ + output_media.push_back(new OutputTCPSocketEvAAL) ; +} + + void Output::write(const ResultList &results) const { for (vector::const_iterator i = output_media.begin() ; diff --git a/owlps-positioning/src/output.hh b/owlps-positioning/src/output.hh index 29d4d15..1a5b26a 100644 --- a/owlps-positioning/src/output.hh +++ b/owlps-positioning/src/output.hh @@ -19,6 +19,7 @@ protected: void initialise_output_terminal(void) ; void initialise_output_csv(void) ; void initialise_output_udp_socket(void) ; + void initialise_output_tcpevaal_socket(void) ; //@} public: diff --git a/owlps-positioning/src/outputtcpsocketevaal.cc b/owlps-positioning/src/outputtcpsocketevaal.cc new file mode 100644 index 0000000..fcb3851 --- /dev/null +++ b/owlps-positioning/src/outputtcpsocketevaal.cc @@ -0,0 +1,157 @@ +#include "outputtcpsocketevaal.hh" +#include "request.hh" +#include "resultlist.hh" +#include "posexcept.hh" + +#include +#include // For perror() + +using namespace std ; + + + +/* *** Constructors *** */ + + +OutputTCPSocketEvAAL::OutputTCPSocketEvAAL( + const string &_remote_host, + const uint_fast16_t _remote_port): + remote_host(_remote_host), remote_port(_remote_port) +{ + if (! init_socket()) + throw error_opening_output_file("TCP socket") ; +} + + +OutputTCPSocketEvAAL::~OutputTCPSocketEvAAL() +{ + close_socket() ; +} + + + +/* *** Operations *** */ + + +/** + * @return \em true if the socket were successfully opened. + * @return \em false in case of error. + */ +bool OutputTCPSocketEvAAL::init_socket() +{ + sockfd = socket(AF_INET, SOCK_STREAM, 0) ; + if (sockfd < 0) + { + perror("TCP socket creation failed") ; + return false ; + } + + struct sockaddr_in server_description ; + memset(&server_description, 0, sizeof(server_description)) ; + server_description.sin_family = AF_INET ; + // Server IP address: + server_description.sin_addr.s_addr = inet_addr(remote_host.c_str()) ; + // Listening port on the server: + server_description.sin_port = htons(remote_port) ; + + int ret = connect(sockfd, (struct sockaddr *)&server_description, + sizeof(server_description)) ; + if (ret < 0) + { + perror("Cannot bind the TCP socket") ; + return false ; + } + + return true ; +} + + +/** + * Normally, the socket is closed automatically by the destructor. Use + * this if you want to close the socket prematurely. + * #sockfd is set to -1, even in case of error. + * @return \em true if the socket were successfully closed or were not + * opened. + * @return \em false in case of error. + */ +bool OutputTCPSocketEvAAL::close_socket() +{ + if (sockfd >= 0) + { + if (close(sockfd)) + { + perror("Cannot close TCP socket") ; + return false ; + } + + sockfd = -1 ; + } + + return true ; +} + + +void OutputTCPSocketEvAAL::write(const Result &result) +{ + const Point3D &position = result.get_position() ; + long timestamp = 1234567l ; // FIXME + int area_of_interest = 0 ; // FIXME + + ostringstream str ; + str + << "OwlPS " + << position.get_x() << ' ' + << position.get_y() << ' ' + << timestamp << ' ' + << area_of_interest << '\n' ; + + if (send_data(str.str())) + acknowledge() ; +} + + +void OutputTCPSocketEvAAL::write(const ResultList &results) +{ + assert(results.get_results().size() == 1) ; + write(results.get_results()[0]) ; +} + + +/** + * Sends the text buffer 'data'. + */ +bool OutputTCPSocketEvAAL::send_data(const string &data) const +{ + ssize_t nsent = send(sockfd, data.c_str(), data.size(), 0) ; + if (nsent != static_cast(data.size())) + { + perror("Error sending result data") ; + return false ; + } + return true ; +} + + +bool OutputTCPSocketEvAAL::acknowledge() const +{ + char ack_buf[10] ; + ssize_t nrecv = recv(sockfd, ack_buf, 10, 0) ; + if (nrecv < 0) + perror("Error receiving acknowledgement") ; + + ack_buf[9] = '\0' ; + string ack(ack_buf) ; + if (ack == "Published") + return true ; + + if (ack == "NotParsed") + { + cerr << "TCP server error: string not parsed.\n" ; + return false ; + } + + cerr + << "TCP server error: unknown acknoledgment string « " + << ack << " ».\n" ; + return false ; +} diff --git a/owlps-positioning/src/outputtcpsocketevaal.hh b/owlps-positioning/src/outputtcpsocketevaal.hh new file mode 100644 index 0000000..b355b59 --- /dev/null +++ b/owlps-positioning/src/outputtcpsocketevaal.hh @@ -0,0 +1,51 @@ +#ifndef _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_ +#define _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_ + +#include "outputmedium.hh" + +#include +#include // is not C++ 98 compliant +#include + +/// Sends results to a remote host by TCP (EvAAL competition format) +/** + * The results are sent through an TCP socket as a string value, + * conforming to the EvAAL competition format. + */ +class OutputTCPSocketEvAAL: public OutputMedium +{ +protected: + int sockfd ; + std::string remote_host ; + uint_fast16_t remote_port ; + + struct sockaddr_in server_info ; + struct sockaddr_in client_info ; + + /** @name Operations */ + //@{ + /// Initialises the socket + bool init_socket(void) ; + /// Sends a string through the socket + bool send_data(const std::string &data) const ; + /// Receives and parse the acknowledgement from the server + bool acknowledge(void) const ; + //@} + +public: + OutputTCPSocketEvAAL(const std::string &_remote_host = "127.0.0.1", + const uint_fast16_t _remote_port = 4444) ; + ~OutputTCPSocketEvAAL(void) ; + + /** @name Operations */ + //@{ + void write(const Result &result) ; + void write(const ResultList &results) ; + /// Closes the socket + bool close_socket(void) ; + //@} +} ; + + + +#endif // _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_ diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 375a150..be4acf4 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -241,8 +241,9 @@ void UserInterface::fill_output_options() options.add_options() ("output.medium,O", po::value< vector >()->composing(), "Medium to which the results will be wrote. You can specify" - " this option more than once. Allowed: Terminal, CSV, UDP." - " If this option is absent, results will be printed on the terminal.") + " this option more than once." + " Allowed: Terminal, CSV, UDP, TCPEvAAL." + " If this option is absent, the results are printed on the terminal.") ("output.csv-file", po::value(), "CSV file to use for output (when output.medium = CSV).") ("output.udp-host", po::value(), From 1dfe30ea039ed4d9e1c6dbdb6dc0024e6f07ddaf Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 12:32:07 +0200 Subject: [PATCH 51/64] [Positioning] Add Result::request Associate a Result with the origin Request. --- owlps-positioning/src/cartographyalgorithm.cc | 2 +- owlps-positioning/src/frbhmbasic.cc | 2 +- .../src/multilaterationalgorithm.cc | 2 +- owlps-positioning/src/realposition.cc | 4 +-- owlps-positioning/src/result.cc | 8 +++-- owlps-positioning/src/result.hh | 30 ++++++++++++++----- 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/owlps-positioning/src/cartographyalgorithm.cc b/owlps-positioning/src/cartographyalgorithm.cc index 0610e2a..5ac94fc 100644 --- a/owlps-positioning/src/cartographyalgorithm.cc +++ b/owlps-positioning/src/cartographyalgorithm.cc @@ -5,5 +5,5 @@ Result CartographyAlgorithm::compute(const Request &request) { Point3D position(select_point(request)) ; - return Result(position, name) ; + return Result(&request, name, position) ; } diff --git a/owlps-positioning/src/frbhmbasic.cc b/owlps-positioning/src/frbhmbasic.cc index d3fba65..1800a9d 100644 --- a/owlps-positioning/src/frbhmbasic.cc +++ b/owlps-positioning/src/frbhmbasic.cc @@ -12,7 +12,7 @@ Result FRBHMBasic::compute(const Request &_request) compute_ap_distance_circles() ; Point3D position(multilaterate_2d(closest_in_ss->get_z())) ; - return Result(position, name) ; + return Result(request, name, position) ; } diff --git a/owlps-positioning/src/multilaterationalgorithm.cc b/owlps-positioning/src/multilaterationalgorithm.cc index 85d5fba..f3f8b57 100644 --- a/owlps-positioning/src/multilaterationalgorithm.cc +++ b/owlps-positioning/src/multilaterationalgorithm.cc @@ -70,7 +70,7 @@ Result MultilaterationAlgorithm::compute(const Request &_request) compute_ap_distance_circles() ; Point3D position(multilaterate()) ; - return Result(position, name) ; + return Result(request, name, position) ; } diff --git a/owlps-positioning/src/realposition.cc b/owlps-positioning/src/realposition.cc index 2de435f..0a9c32f 100644 --- a/owlps-positioning/src/realposition.cc +++ b/owlps-positioning/src/realposition.cc @@ -17,7 +17,7 @@ Result RealPosition::compute(const Request &request) coordinates = request.get_real_position() ; if (coordinates) - return Result(*coordinates, name) ; + return Result(&request, name, *coordinates) ; - return Result(name) ; + return Result(&request, name) ; } diff --git a/owlps-positioning/src/result.cc b/owlps-positioning/src/result.cc index 149d441..0698494 100644 --- a/owlps-positioning/src/result.cc +++ b/owlps-positioning/src/result.cc @@ -10,9 +10,11 @@ using namespace std ; /* *** Constructors *** */ -Result::Result(const Point3D &_position, const std::string &_algorithm, +Result::Result(const Request *_request, + const std::string &_algorithm, + const Point3D &_position, const Point3D &real_position): - position(_position), algorithm(_algorithm) + request(_request), algorithm(_algorithm), position(_position) { compute_error(real_position) ; } @@ -37,6 +39,7 @@ const Result& Result::operator=(const Result &source) if (this == &source) return *this ; + request = source.request ; algorithm = source.algorithm ; position = source.position ; error = source.error ; @@ -48,6 +51,7 @@ const Result& Result::operator=(const Result &source) bool Result::operator==(const Result &source) const { return + request == source.request && algorithm == source.algorithm && position == source.position && error == source.error ; diff --git a/owlps-positioning/src/result.hh b/owlps-positioning/src/result.hh index 6792782..7e41ff0 100644 --- a/owlps-positioning/src/result.hh +++ b/owlps-positioning/src/result.hh @@ -1,6 +1,8 @@ #ifndef _OWLPS_POSITIONING_RESULT_HH_ #define _OWLPS_POSITIONING_RESULT_HH_ +class Request ; + #include "point3d.hh" #include @@ -9,25 +11,31 @@ class Result { protected: - /// Computed coordinates of the mobile - Point3D position ; + /// Request sent by the mobile + const Request *request ; /// Algorithm used to compute the position std::string algorithm ; + /// Computed coordinates of the mobile + Point3D position ; /// Distance error between the real coordinates and the computed point /** The error is set to -1 if the real coordinates are unknown. */ float error ; public: - Result(const std::string &_algorithm = "UnknownAlgorithm"): - algorithm(_algorithm), error(-1) {} - Result(const Point3D &_position, const std::string &_algorithm): - position(_position), algorithm(_algorithm), error(-1) {} - Result(const Point3D &_position, const std::string &_algorithm, - const Point3D &real_position) ; + Result(const Request *_request = NULL, + const std::string &_algorithm = "UnknownAlgorithm"): + request(_request), algorithm(_algorithm), error(-1) {} + Result(const Request *_request, const std::string &_algorithm, + const Point3D &_position): + request(_request), algorithm(_algorithm), position(_position), + error(-1) {} + Result(const Request *_request, const std::string &_algorithm, + const Point3D &_position, const Point3D &real_position) ; ~Result(void) {} /** @name Read accessors */ //@{ + const Request* get_request(void) const ; const std::string& get_algorithm(void) const ; const Point3D& get_position(void) const ; float get_error(void) const ; @@ -60,6 +68,12 @@ public: /* *** Read accessors *** */ +inline const Request* Result::get_request() const +{ + return request ; +} + + inline const std::string& Result::get_algorithm() const { return algorithm ; From 9f5305b496573a18f80e3139068da3ba851427ad Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 12:35:33 +0200 Subject: [PATCH 52/64] [Positioning] TCPEvAAL: send request's timestamp --- owlps-positioning/src/outputtcpsocketevaal.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/owlps-positioning/src/outputtcpsocketevaal.cc b/owlps-positioning/src/outputtcpsocketevaal.cc index fcb3851..8005a43 100644 --- a/owlps-positioning/src/outputtcpsocketevaal.cc +++ b/owlps-positioning/src/outputtcpsocketevaal.cc @@ -94,7 +94,7 @@ bool OutputTCPSocketEvAAL::close_socket() void OutputTCPSocketEvAAL::write(const Result &result) { const Point3D &position = result.get_position() ; - long timestamp = 1234567l ; // FIXME + Timestamp request_time = result.get_request()->get_time_sent() ; int area_of_interest = 0 ; // FIXME ostringstream str ; @@ -102,7 +102,7 @@ void OutputTCPSocketEvAAL::write(const Result &result) << "OwlPS " << position.get_x() << ' ' << position.get_y() << ' ' - << timestamp << ' ' + << static_cast(request_time) << ' ' << area_of_interest << '\n' ; if (send_data(str.str())) @@ -110,6 +110,10 @@ void OutputTCPSocketEvAAL::write(const Result &result) } +/** + * @param results Must contain only one element, since the EvAAL format + * accepts only one algorithm result. + */ void OutputTCPSocketEvAAL::write(const ResultList &results) { assert(results.get_results().size() == 1) ; From a951717433475fba23f821f78ab8ffac744deb2c Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 13:22:46 +0200 Subject: [PATCH 53/64] [Positioning] Add Stock::in_which_area_is() --- owlps-positioning/src/stock.cc | 21 +++++++++++++++++++++ owlps-positioning/src/stock.hh | 2 ++ 2 files changed, 23 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 53cf043..01e4304 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -1,6 +1,7 @@ #include "stock.hh" #include "configuration.hh" #include "posexcept.hh" +#include "area.hh" using namespace std ; using std::tr1::unordered_map ; @@ -80,6 +81,26 @@ const Building& Stock::get_building(const string &name) } +/** + * @returns A pointer to the first Area in which \em point was found. + * @returns NULL if \em point does not belong to any Area. + */ +const Area* Stock::in_which_area_is(const Point3D point) +{ + for (unordered_map::const_iterator + b = buildings.begin() ; b != buildings.end() ; ++b) + { + const unordered_map &areas = b->second.get_areas() ; + for (unordered_map::const_iterator + a = areas.begin() ; a != areas.end() ; ++a) + if (a->second->contains_point(point)) + return a->second ; + } + + return NULL ; +} + + /* *** Waypoint operations *** */ diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index fb8a50a..8c4cac7 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -50,6 +50,8 @@ public: static const Building& get_building(const std::string &name) ; /// Searches for a Building and creates it if it does not exist static const Building& find_create_building(const std::string &name) ; + /// Searches the Area in which \em point is + static const Area* in_which_area_is(const Point3D point) ; //@} /** @name Waypoint operations */ From 593da5e42291d28d99560b62059a4a6e7b2efd5c Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 13:49:01 +0200 Subject: [PATCH 54/64] [Positioning] TCPEvAAL: send area of interest The areas of interest must be defined as areas in the topology configuration file. Their names must be integer values, to conform with the EvAAL naming. --- owlps-positioning/src/outputtcpsocketevaal.cc | 43 +++++++++++++++---- owlps-positioning/src/outputtcpsocketevaal.hh | 6 ++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/owlps-positioning/src/outputtcpsocketevaal.cc b/owlps-positioning/src/outputtcpsocketevaal.cc index 8005a43..e460510 100644 --- a/owlps-positioning/src/outputtcpsocketevaal.cc +++ b/owlps-positioning/src/outputtcpsocketevaal.cc @@ -1,10 +1,13 @@ #include "outputtcpsocketevaal.hh" #include "request.hh" #include "resultlist.hh" +#include "area.hh" +#include "stock.hh" #include "posexcept.hh" #include #include // For perror() +#include using namespace std ; @@ -91,11 +94,22 @@ bool OutputTCPSocketEvAAL::close_socket() } +/** + * @param results Must contain only one element, since the EvAAL format + * accepts only one algorithm result. + */ +void OutputTCPSocketEvAAL::write(const ResultList &results) +{ + assert(results.get_results().size() == 1) ; + write(results.get_results()[0]) ; +} + + void OutputTCPSocketEvAAL::write(const Result &result) { const Point3D &position = result.get_position() ; Timestamp request_time = result.get_request()->get_time_sent() ; - int area_of_interest = 0 ; // FIXME + int area_of_interest = area_of_interest_number(position) ; ostringstream str ; str @@ -110,14 +124,27 @@ void OutputTCPSocketEvAAL::write(const Result &result) } -/** - * @param results Must contain only one element, since the EvAAL format - * accepts only one algorithm result. - */ -void OutputTCPSocketEvAAL::write(const ResultList &results) +int OutputTCPSocketEvAAL:: +area_of_interest_number(const Point3D &position) const { - assert(results.get_results().size() == 1) ; - write(results.get_results()[0]) ; + const Area *area = Stock::in_which_area_is(position) ; + if (area == NULL) + return 0 ; + + int aoi_number = 0 ; + try + { + aoi_number = boost::lexical_cast(area->get_name()) ; + } + catch (boost::bad_lexical_cast &e) + { + cerr + << "Cannot convert the area of interest's name (« " + << area->get_name() << " ») into an integer value: " + << e.what() << '\n' ; + } + + return aoi_number ; } diff --git a/owlps-positioning/src/outputtcpsocketevaal.hh b/owlps-positioning/src/outputtcpsocketevaal.hh index b355b59..791761a 100644 --- a/owlps-positioning/src/outputtcpsocketevaal.hh +++ b/owlps-positioning/src/outputtcpsocketevaal.hh @@ -1,6 +1,8 @@ #ifndef _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_ #define _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_ +class Point3D ; + #include "outputmedium.hh" #include @@ -39,8 +41,10 @@ public: /** @name Operations */ //@{ - void write(const Result &result) ; void write(const ResultList &results) ; + void write(const Result &result) ; + /// Get the area of interest number from the position + int area_of_interest_number(const Point3D &position) const ; /// Closes the socket bool close_socket(void) ; //@} From 42bcef2c0ebe3143b797d7d36c26fd9612ba7c2e Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Sun, 24 Jul 2011 17:25:00 +0200 Subject: [PATCH 55/64] [Positioning] Add options tcpevaal-{host,port} Add options output.tcpevaal-host and output.tcpevaal-port, with localhost:4444 as default values, as recommended by the organisers. --- owlps-positioning/src/output.cc | 5 ++++- owlps-positioning/src/outputtcpsocketevaal.hh | 4 ++-- owlps-positioning/src/userinterface.cc | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/owlps-positioning/src/output.cc b/owlps-positioning/src/output.cc index 43cbee3..4e91017 100644 --- a/owlps-positioning/src/output.cc +++ b/owlps-positioning/src/output.cc @@ -100,7 +100,10 @@ void Output::initialise_output_udp_socket() void Output::initialise_output_tcpevaal_socket() { - output_media.push_back(new OutputTCPSocketEvAAL) ; + output_media.push_back( + new OutputTCPSocketEvAAL( + Configuration::string_value("output.tcpevaal-host"), + Configuration::int_value("output.tcpevaal-port"))) ; } diff --git a/owlps-positioning/src/outputtcpsocketevaal.hh b/owlps-positioning/src/outputtcpsocketevaal.hh index 791761a..281b71a 100644 --- a/owlps-positioning/src/outputtcpsocketevaal.hh +++ b/owlps-positioning/src/outputtcpsocketevaal.hh @@ -35,8 +35,8 @@ protected: //@} public: - OutputTCPSocketEvAAL(const std::string &_remote_host = "127.0.0.1", - const uint_fast16_t _remote_port = 4444) ; + OutputTCPSocketEvAAL(const std::string &_remote_host, + const uint_fast16_t _remote_port) ; ~OutputTCPSocketEvAAL(void) ; /** @name Operations */ diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index be4acf4..5bc2726 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -17,6 +17,9 @@ namespace po = boost::program_options ; #define DEFAULT_CONFIG_FILE_NAME \ "/usr/local/etc/owlps/owlps-positioning.cfg" +#define DEFAULT_TCPEVAAL_HOST "127.0.0.1" +#define DEFAULT_TCPEVAAL_PORT 4444 + /* *** Constructors *** */ @@ -251,6 +254,12 @@ void UserInterface::fill_output_options() ("output.udp-port", po::value() ->default_value(MOBILE_DEFAULT_PORT), "Port on which the UDP data is sent (when output.medium = UDP).") + ("output.tcpevaal-host", po::value() + ->default_value(DEFAULT_TCPEVAAL_HOST), + "Host to which the TCP data is sent (when output.medium = TCPEvAAL).") + ("output.tcpevaal-port", po::value() + ->default_value(DEFAULT_TCPEVAAL_PORT), + "Port on which the TCP data is sent (when output.medium = TCPEvAAL).") ; file_options->add(options) ; From c11e33fd0bdd946101df8c4f63c237ac792fa853 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 25 Jul 2011 16:50:35 +0200 Subject: [PATCH 56/64] [Positioning] Add missing #include --- owlps-positioning/src/input.cc | 1 + owlps-positioning/src/outputtcpsocketevaal.cc | 1 + owlps-positioning/src/positioning.cc | 2 ++ owlps-positioning/src/stock.cc | 2 ++ 4 files changed, 6 insertions(+) diff --git a/owlps-positioning/src/input.cc b/owlps-positioning/src/input.cc index 4708947..40db41d 100644 --- a/owlps-positioning/src/input.cc +++ b/owlps-positioning/src/input.cc @@ -7,6 +7,7 @@ #include "posexcept.hh" #include "stock.hh" +#include #include using namespace std ; diff --git a/owlps-positioning/src/outputtcpsocketevaal.cc b/owlps-positioning/src/outputtcpsocketevaal.cc index e460510..11fa53e 100644 --- a/owlps-positioning/src/outputtcpsocketevaal.cc +++ b/owlps-positioning/src/outputtcpsocketevaal.cc @@ -5,6 +5,7 @@ #include "stock.hh" #include "posexcept.hh" +#include #include #include // For perror() #include diff --git a/owlps-positioning/src/positioning.cc b/owlps-positioning/src/positioning.cc index 0e94cd9..e494fd0 100644 --- a/owlps-positioning/src/positioning.cc +++ b/owlps-positioning/src/positioning.cc @@ -11,6 +11,8 @@ #include +#include + using namespace std ; diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 01e4304..9ee4dab 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -3,6 +3,8 @@ #include "posexcept.hh" #include "area.hh" +#include + using namespace std ; using std::tr1::unordered_map ; using std::tr1::unordered_set ; From 84acee629c3fcb5580bfe7fa1e796f7866d63ea4 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 25 Jul 2011 19:23:20 +0200 Subject: [PATCH 57/64] [Positioning] Add Stock::reference_point_exists() --- owlps-positioning/src/stock.cc | 8 ++++++++ owlps-positioning/src/stock.hh | 2 ++ 2 files changed, 10 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 9ee4dab..9fc3407 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -342,6 +342,14 @@ bool Stock::is_ap_coordinate(const Point3D &coord) /* *** ReferencePoint operations *** */ +bool Stock::reference_point_exists(const ReferencePoint &point) +{ + unordered_set::const_iterator i = + reference_points.find(point) ; + return i != reference_points.end() ; +} + + /** * @param point Coordinates of the wanted ReferencePoint. * @return The ReferencePoint at the given coordinates, if found. diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index 8c4cac7..bfd6c25 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -122,6 +122,8 @@ public: //@{ /// Returns the number of reference points static unsigned int nb_reference_points(void) ; + /// Verify the existence of a reference point at the given coordinates + static bool reference_point_exists(const ReferencePoint &point) ; /// Reads the ReferencePoint at the given coordinates static const ReferencePoint& get_reference_point(const ReferencePoint &point) ; From a1dd6d90d8ea9d001ce1506ee43a043e02dd28db Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Mon, 25 Jul 2011 19:24:10 +0200 Subject: [PATCH 58/64] [Positioning] Fix RP generation with >3 APs When selecting the 2 reference APs, skip the APs that do not have (yet) an associated reference point. --- owlps-positioning/src/stock.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index 9fc3407..b508aba 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -520,6 +520,10 @@ void Stock::regenerate_reference_points() continue ; const Point3D &ref_coord = ref->second.get_coordinates() ; + // Skip the AP if the associated reference point does + // not exist yet: + if (! reference_point_exists(ref_coord)) + continue ; double angle = rx_coord.angle(current_point, ref_coord) ; pair Date: Tue, 26 Jul 2011 15:23:15 +0200 Subject: [PATCH 59/64] [Positioning] Stock::store_CR() returns the CR Stock::store_calibration_request() now returns the stored/found calibration request. --- owlps-positioning/src/stock.cc | 6 +++++- owlps-positioning/src/stock.hh | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index b508aba..ceb8ee2 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -624,12 +624,16 @@ void Stock::regenerate_reference_points() /* *** CalibrationRequest operations *** */ -void Stock:: +/** + * @returns The CalibrationRequest created or found. + */ +const CalibrationRequest& Stock:: store_calibration_request(const CalibrationRequest &request) { const CalibrationRequest &calibration_request = find_create_calibration_request(request) ; calibration_request.reference_point_backward_link() ; + return calibration_request ; } diff --git a/owlps-positioning/src/stock.hh b/owlps-positioning/src/stock.hh index bfd6c25..60bc7fe 100644 --- a/owlps-positioning/src/stock.hh +++ b/owlps-positioning/src/stock.hh @@ -145,7 +145,7 @@ public: static unsigned int nb_calibration_requests(void) ; /// \brief Searches for a CalibrationRequest, adds it if it does /// not exist, and links it to its reference point - static void store_calibration_request( + static const CalibrationRequest& store_calibration_request( const CalibrationRequest &request) ; /// Deletes a CalibrationRequest static void delete_calibration_request( From 8295666178ccddb5332c314ac20e4166e46e27a4 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 29 Jul 2011 00:05:52 +0200 Subject: [PATCH 60/64] [Positioning] Add Result::in_which_area() --- owlps-positioning/Makefile | 2 ++ owlps-positioning/src/result.cc | 16 ++++++++++++++++ owlps-positioning/src/result.hh | 1 + 3 files changed, 19 insertions(+) diff --git a/owlps-positioning/Makefile b/owlps-positioning/Makefile index f720f45..fe62d29 100644 --- a/owlps-positioning/Makefile +++ b/owlps-positioning/Makefile @@ -203,6 +203,8 @@ $(OBJ_DIR)/calibrationrequest.o: \ $(OBJ_DIR)/referencepoint.o \ $(OBJ_DIR)/direction.o $(OBJ_DIR)/result.o: \ + $(OBJ_DIR)/stock.o \ + $(OBJ_DIR)/area.o \ $(OBJ_DIR)/request.o $(OBJ_DIR)/resultlist.o: \ $(OBJ_DIR)/result.o diff --git a/owlps-positioning/src/result.cc b/owlps-positioning/src/result.cc index 0698494..3816c06 100644 --- a/owlps-positioning/src/result.cc +++ b/owlps-positioning/src/result.cc @@ -1,5 +1,7 @@ #include "result.hh" #include "request.hh" +#include "area.hh" +#include "stock.hh" #include @@ -21,6 +23,20 @@ Result::Result(const Request *_request, +/* *** Read accessors *** */ + + +string Result::in_which_area() const +{ + const Area *area = Stock::in_which_area_is(position) ; + if (area == NULL) + return "" ; + + return area->get_name() ; +} + + + /* *** Write accessors *** */ diff --git a/owlps-positioning/src/result.hh b/owlps-positioning/src/result.hh index 7e41ff0..108b660 100644 --- a/owlps-positioning/src/result.hh +++ b/owlps-positioning/src/result.hh @@ -39,6 +39,7 @@ public: const std::string& get_algorithm(void) const ; const Point3D& get_position(void) const ; float get_error(void) const ; + std::string in_which_area(void) const ; //@} /** @name Write accessors */ From 089c8e3f8f6c484f5031902ac22219b47bf05126 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 29 Jul 2011 00:06:40 +0200 Subject: [PATCH 61/64] [Positioning] Result: operator<< displays area If the result point is in a known area, the area's name is displayed (this changes the output of OutputTerminal). --- owlps-positioning/src/result.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/owlps-positioning/src/result.cc b/owlps-positioning/src/result.cc index 3816c06..8a74ec4 100644 --- a/owlps-positioning/src/result.cc +++ b/owlps-positioning/src/result.cc @@ -99,7 +99,8 @@ std::ostream& operator<<(ostream &os, const Result &r) { os << "The result of the algorithm " << r.algorithm - << " is: " << r.position ; + << " is: " << r.position + << " (area: « " << r.in_which_area() << " »)" ; if (r.error >= 0) os << ", error = " << r.error << " m" ; return os ; From 0da98cdb0561532543b7da592cec5d43bf1ea5f3 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 29 Jul 2011 00:47:24 +0200 Subject: [PATCH 62/64] [Positioning] Opt. radar-ignore-ap-reference-points Add the option positioning.radar-ignore-ap-reference-points, to be able to select only generated reference points. --- owlps-positioning/cfg/owlps-positioning.cfg | 7 ++++ owlps-positioning/src/stock.cc | 37 +++++++++++++++++++++ owlps-positioning/src/userinterface.cc | 4 +++ 3 files changed, 48 insertions(+) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index 2a57570..ead103c 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -63,6 +63,13 @@ csv-file = /tmp/owlps-positioning.log # request is compared directly to each calibration request. #radar-average-reference-points = false +# With the RADAR algorithm, do not select reference points on which an +# AP is sit, as far as possible (i.e. if there are reference points +# where no AP sits). This is useful if you are using autocalibration +# and want to select only the generated reference points. +# The default is false. +#radar-ignore-ap-reference-points = false + # Generate reference points from the (auto)calibration requests # received. #generate-reference-points = false diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index ceb8ee2..d9aca8a 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -387,13 +387,31 @@ closest_reference_point(const Request &request) "Cannot search for the closest reference point: reference points'" " list is empty!") ; + bool ignore_aps = Configuration::bool_value( + "positioning.radar-ignore-ap-reference-points") ; unordered_set::const_iterator i = reference_points.begin() ; + + if (ignore_aps) + { + // Fast-forward to the next non-AP reference point + while (i != reference_points.end() && is_ap_coordinate(*i)) + ++i ; + + // No non-AP reference point was found, we are forced to consider + // the AP reference points + if (i == reference_points.end()) + ignore_aps = false ; + } + float distance = i->ss_square_distance(request) ; unordered_set::const_iterator closest = i ; for (++i ; i != reference_points.end() ; ++i) { + if (ignore_aps && is_ap_coordinate(*i)) + continue ; + float tmp_distance = i->ss_square_distance(request) ; if (tmp_distance < distance) { @@ -673,13 +691,32 @@ closest_calibration_request(const Request &request) "Cannot search for the closest calibration request: calibration" " requests' list is empty!") ; + bool ignore_aps = Configuration::bool_value( + "positioning.radar-ignore-ap-reference-points") ; unordered_set::const_iterator i = calibration_requests.begin() ; + + if (ignore_aps) + { + // Fast-forward to the next non-AP reference point + while (i != calibration_requests.end() && + is_ap_coordinate(*i->get_reference_point())) + ++i ; + + // No non-AP reference point was found, we are forced to consider + // the AP reference points + if (i == calibration_requests.end()) + ignore_aps = false ; + } + float distance = i->ss_square_distance(request) ; unordered_set::const_iterator closest = i ; for (++i ; i != calibration_requests.end() ; ++i) { + if (ignore_aps && is_ap_coordinate(*i->get_reference_point())) + continue ; + float tmp_distance = i->ss_square_distance(request) ; if (tmp_distance < distance) { diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index 5bc2726..d735580 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -204,6 +204,10 @@ void UserInterface::fill_positioning_options() po::value()->default_value(0.5), "When generating reference points, this distance (in meters) will" " separate each point to the next.") + ("positioning.radar-ignore-ap-reference-points", + po::value()->default_value(false), + "With the RADAR algorithm, try to avoid selecting the reference" + " points which are coordinates of an AP.") ("positioning.accept-new-calibration-requests", po::value()->default_value(false), "Add the calibration requests received during the run-time to" From a9f4750f3437d0bb3eadef014eafddcd5b16f2ae Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 29 Jul 2011 16:14:39 +0200 Subject: [PATCH 63/64] [Positioning] Split option generated-meshing-grain Split the option positioning.generated-meshing-grain in two: positioning.generated-meshing-grain-x and positioning.generated-meshing-grain-y. --- owlps-positioning/cfg/owlps-positioning.cfg | 6 ++++-- owlps-positioning/src/stock.cc | 12 +++++++----- owlps-positioning/src/userinterface.cc | 8 ++++++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/owlps-positioning/cfg/owlps-positioning.cfg b/owlps-positioning/cfg/owlps-positioning.cfg index ead103c..21c3a71 100644 --- a/owlps-positioning/cfg/owlps-positioning.cfg +++ b/owlps-positioning/cfg/owlps-positioning.cfg @@ -75,8 +75,10 @@ csv-file = /tmp/owlps-positioning.log #generate-reference-points = false # When the above option is activated, the reference points are generated -# with the specified distance (in meters) between one another. -#generated-meshing-grain = 0.5 +# with the specified distance (in meters) between one another, in the X +# and Y axis. +#generated-meshing-grain-x = 0.5 +#generated-meshing-grain-y = 0.5 # This option allows the calibration requests sent during the # positioning phase to be added to the calibration request's list. They diff --git a/owlps-positioning/src/stock.cc b/owlps-positioning/src/stock.cc index d9aca8a..d020a63 100644 --- a/owlps-positioning/src/stock.cc +++ b/owlps-positioning/src/stock.cc @@ -486,12 +486,14 @@ void Stock::regenerate_reference_points() Configuration::string_value("positioning.minmax-start")) ; Point3D stop( Configuration::string_value("positioning.minmax-stop")) ; - float step = - Configuration::float_value("positioning.generated-meshing-grain") ; + float step_x = + Configuration::float_value("positioning.generated-meshing-grain-x") ; + float step_y = + Configuration::float_value("positioning.generated-meshing-grain-y") ; float z = 1 ; // FIXME - 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) + for (float x = start.get_x() ; x <= stop.get_x() ; x += step_x) + for (float y = start.get_y() ; y <= stop.get_y() ; y += step_y) + //for (float z = start.get_z() ; z <= stop.get_z() ; z += step_z) { Point3D current_point(x,y,z) ; diff --git a/owlps-positioning/src/userinterface.cc b/owlps-positioning/src/userinterface.cc index d735580..e229189 100644 --- a/owlps-positioning/src/userinterface.cc +++ b/owlps-positioning/src/userinterface.cc @@ -200,10 +200,14 @@ void UserInterface::fill_positioning_options() po::value()->default_value(false), "Generate reference points from the (auto)calibration requests" " received.") - ("positioning.generated-meshing-grain", + ("positioning.generated-meshing-grain-x", po::value()->default_value(0.5), "When generating reference points, this distance (in meters) will" - " separate each point to the next.") + " separate each point to the next in X.") + ("positioning.generated-meshing-grain-y", + po::value()->default_value(0.5), + "When generating reference points, this distance (in meters) will" + " separate each point to the next in Y.") ("positioning.radar-ignore-ap-reference-points", po::value()->default_value(false), "With the RADAR algorithm, try to avoid selecting the reference" From 1a5fab9b992dade09bbf760fef17d86fa4fb9063 Mon Sep 17 00:00:00 2001 From: Matteo Cypriani Date: Fri, 29 Jul 2011 22:26:38 +0200 Subject: [PATCH 64/64] Update TODOs --- TODO | 36 ++++++++++---------- owlps-positioning/TODO | 77 ++++++++++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/TODO b/TODO index 00e88ef..f46cbb2 100644 --- a/TODO +++ b/TODO @@ -1,11 +1,14 @@ * Global +- Add option dump-configuration (displays the config & exits). - Makefiles: ° Translate comments & help. + ° Merge Makefile and Makefile_atheros*. Use template makefiles, + autohell, cmake…? - Use string for network exchanges? - Mark arguments as const in function headers if needed - That is (mostly) done in the owlps-positioning C++ code, but not - constantly in C modules. + Mostly done in the owlps-positioning C++ code (should check that), + but not constantly in C modules. [Done in libowlps & libowlps-client.] - Allow to use hostnames instead of IP addresses in all modules getaddrinfo(3) (or gethostbyname(3)) should be used when opening @@ -25,10 +28,14 @@ * Aggregator +- -o should be optional. +- Add an option to (not) flush the output file. +- Refactor: + ° monitor_requests() + ° got_request() - inet_ntoa() is not secure with threads (But it is currently used by only one thread.) Use inet_ntop() instead? -- Refactor got_request(). - Use the type of a request to identify it? (along with the mobile MAC address and the request time) - got_request(): option for the maximal difference time @@ -36,36 +43,29 @@ and received within an interval of 10ms are part of the same request. We should define an option to allow user to choose the time he wants. -- Allow blank parameters for output options. * Listener - Refactor and review read_packet(). +- Handle better the configuration file reading + Get rid of the "Cannot open configuration file" error, in quiet + mode and when the default configuration file has to be used (no + file specified by the user with -f). - Listen for autocalibration requests without sending requests? - read_packet(): use ieee80211_header_size for all implicit packets Currently the size is corrected only for data packets. -- Move endianess #defines in libowlps? -- Merge Makefile and Makefile_atheros? - Use autohell, cmake, etc.? -- Use positive (USE_CONFUSE) and negative (NO_USE_PTHREAD) options? - The default options could be modified, but that's not so important, - is it? * Client +- Handle signals. +- Add verbose & quiet options. +- Log sent requests? - Allow to use a string for the direction? Could be nice, but probably useless. * Positioning -- Has its own fat TODO file, which I should translate. - - -* writeInDb - -- Do something about that - ° Merge in owlps-positioning? - ° Delete? +- Has its own fat TODO file, which I could merge in here. diff --git a/owlps-positioning/TODO b/owlps-positioning/TODO index 1ac4534..3bf131e 100644 --- a/owlps-positioning/TODO +++ b/owlps-positioning/TODO @@ -1,17 +1,60 @@ -- Multithread algorithm calls. +- Known bugs + ° FBCM always gives the same result. + ° Cannot compute the error (Real) with autocalibration requests. -- Write a class for Request::type? +- Algorithms + ° Check MultilaterationAlgorithm::make_constant_term(). + Hint: mobile.trx_power() vs. ap.trx_power(). + ° MinMax: use a different step for X, Y and Z? + +- Autocalibration + ° Generate reference points in 3D. + ° Handle 2 APs, not only >2 APs. + ° Find why some CalibrationRequest were not deleted when + calling Stock::delete_calibration_request() (via + ReferencePoint::delete_requests()). + +- Refactoring + ° Split Stock::regenerate_reference_points() into several + functions. + ° Create virtual class OutputSocket to factorise code of + OutputUDPSocket & OutputTCPSocketEvAAL. + ° Synchronise InputCSV & InputUDPSocket (calibration requests), + factorise code into InputMedium. + ° Write a class for Request::type? CalibrationRequest::direction uses a dedicated class Direction, why not Request::type? That would simplify writing of the type to streams (no need to cast each time anymore). + ° Wi-Fi devices' list + . Merge Stock::mobiles & Stock::aps? + . Factorise AccessPointsReaderCSV & MobilesReaderCSV? + ° Members renaming + . InputMedium: + . - current_line_nb & get_current_line_nb() + . - get_next_request() −> read_next_request() + . Input: get_next_request() −> read_next_request() + . Area: p_min et p_max −> coord_min et coord_max - User interface + ° Add the area to the result in OutputCSV. + ° When reading the APs, add them to the mobiles' list (or another + way to be able to have a single entry for an AP). + ° Rename minmax-start & stop, since it is used elsewhere (grep + minmax-start). + ° Review the option names & descriptions. + ° Add option positioning.self-calibrate (or autocalibrate), to + activate automatically the options needed by the autocalibration. ° Improve --verbose (and/or debug level): print the options, etc. ° Case-insensitive string comparison (for algorithm names, etc.). ° Use a prefix for configuration files (search for config files set with relative path in owlps-positioning.cfg in the same directory). +- Optimisation & code improvement + ° Multithread algorithm calls. + ° ReferencePoint: the request list should be an unordered_set + instead of a vector, to guarantee the unicity of the elements. + - Unit tests ° Update tests (currently unmaintained). ° Unfinished tests: @@ -20,6 +63,9 @@ . Output . Positioning ° Test InterlinkNetworks::compute() ? + ° Timestamp: there is a probability of 10^-6 that the value in + nanoseconds and the rounded value in milliseconds are identical, in + which case some tests can fail. - Revoir le diagramme UML ° Associations : devraient êtres représentées par des attributs @@ -27,25 +73,6 @@ ° Compositions : devraient être représentées par des attributs normaux. -- Building - Dans le destructeur, vérifier qu'il faut bien supprimer les Area et - les Waypoint. Si oui, faut-il aussi les enlever des listes dans - Stock ? (Pour l'instant ils ne sont pas dans Stock.) - -- ReferencePoint - ° La liste des requêtes devrait être un unordered_set (et pas un - vector), pour garantir l'unicité des entrées. - -- MinMax - ° Différencier le pas pour X, Y et Z ? - -- Members renaming - ° InputMedium: - °° current_line_nb & get_current_line_nb() - °° get_next_request() −> read_next_request() - ° Input: get_next_request() −> read_next_request() - ° Area: p_min et p_max −> coord_min et coord_max - - « C++ en action » ° Espaces de noms ? 109 ° Réserver l'espace mémoire des vector avec reserve(). 217 @@ -59,11 +86,3 @@ publics. La classe Direction (et maintenant Timestamp) tend à respecter ce principe en utilisant mieux les opérateurs et en ne proposant pas d'accesseur direct. - -- Miscellaneous - ° Pointer function arguments: const * const - -- Timestamp - Dans les tests, il y a une probabilité de 1/1000000 que la valeur - en ns et la valeur arrondie en ms soient identiques. Dans ce cas, - certains tests peuvent échouer.