Merge branch dev (v1.1.7) into dev-drone
This commit is contained in:
commit
e823014708
36
TODO
36
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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ OBJ_LIST = \
|
|||
userinterface.o \
|
||||
inputdatareader.o \
|
||||
accesspointsreadercsv.o \
|
||||
mobilesreadercsv.o \
|
||||
topologyreadercsv.o \
|
||||
textfilereader.o \
|
||||
csvfilereader.o \
|
||||
|
@ -90,6 +91,7 @@ OBJ_LIST = \
|
|||
outputterminal.o \
|
||||
outputcsv.o \
|
||||
outputudpsocket.o \
|
||||
outputtcpsocketevaal.o \
|
||||
positioning.o \
|
||||
input.o \
|
||||
inputcsv.o \
|
||||
|
@ -139,6 +141,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 \
|
||||
|
@ -154,6 +157,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
|
||||
|
@ -161,6 +165,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 \
|
||||
|
@ -195,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
|
||||
|
@ -239,6 +249,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
|
||||
|
@ -246,6 +259,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: \
|
||||
|
|
|
@ -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 <type>
|
||||
|
||||
- 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.
|
||||
|
|
|
@ -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
|
|
|
@ -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.
|
||||
|
@ -59,6 +63,59 @@ 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
|
||||
|
||||
# When the above option is activated, the reference points are generated
|
||||
# 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
|
||||
# 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
|
||||
|
||||
# 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
|
||||
# by an unknown AP.
|
||||
# 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.
|
||||
# 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.
|
||||
|
|
|
@ -13,7 +13,7 @@ using namespace std ;
|
|||
AccessPointsReaderCSV::AccessPointsReaderCSV(const string &file_name):
|
||||
file(file_name)
|
||||
{
|
||||
read_access_points() ;
|
||||
read_devices() ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,18 +21,19 @@ 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))
|
||||
throw malformed_input_data("Cannot read access point MAC address!") ;
|
||||
PosUtil::to_upper(mac) ;
|
||||
|
||||
Point3D coord ;
|
||||
if (! file.read_point3d(coord))
|
||||
|
@ -52,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) ;
|
||||
}
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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…
|
||||
|
|
|
@ -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) ;
|
||||
|
|
|
@ -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) ;
|
||||
//@}
|
||||
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
Result CartographyAlgorithm::compute(const Request &request)
|
||||
{
|
||||
Point3D position(select_point(request)) ;
|
||||
return Result(position, name) ;
|
||||
return Result(&request, name, position) ;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,12 @@ int Configuration::int_value(const string &key)
|
|||
}
|
||||
|
||||
|
||||
float Configuration::float_value(const string &key)
|
||||
{
|
||||
return configuration[key].as<float>() ;
|
||||
}
|
||||
|
||||
|
||||
bool Configuration::bool_value(const string &key)
|
||||
{
|
||||
return configuration[key].as<bool>() ;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -101,9 +101,9 @@ bool CSVFileReader::read_point3d(Point3D &p)
|
|||
|
||||
try
|
||||
{
|
||||
coord[i] = boost::lexical_cast<float>(*token_iterator) ;
|
||||
coord[i] = lexical_cast<float>(*token_iterator) ;
|
||||
}
|
||||
catch (boost::bad_lexical_cast &e)
|
||||
catch (bad_lexical_cast &e)
|
||||
{
|
||||
print_error_cast() ;
|
||||
return false ;
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "posexcept.hh"
|
||||
#include "stock.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using namespace std ;
|
||||
|
@ -113,8 +114,39 @@ 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, and if it is not empty)
|
||||
if (Configuration::bool_value(
|
||||
"positioning.accept-new-calibration-requests")
|
||||
&& request)
|
||||
{
|
||||
CalibrationRequest *calibration_request =
|
||||
dynamic_cast<CalibrationRequest*>(
|
||||
const_cast<Request*>(&request)) ;
|
||||
if (calibration_request != NULL)
|
||||
{
|
||||
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() ;
|
||||
|
||||
if (! Configuration::bool_value(
|
||||
"positioning.position-calibration-requests"))
|
||||
medium->clear_current_request() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return medium->get_current_request() ;
|
||||
|
|
|
@ -45,6 +45,12 @@ const Request& InputCSV::get_next_request()
|
|||
cerr << "InputCSV: cannot read mac_mobile.\n" ;
|
||||
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) ;
|
||||
|
||||
|
@ -114,11 +120,21 @@ const Request& InputCSV::get_next_request()
|
|||
cerr << "InputCSV: cannot read mac_ap.\n" ;
|
||||
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) ;
|
||||
}
|
||||
|
||||
if (measurements.empty())
|
||||
{
|
||||
current_request->clear() ;
|
||||
return *current_request ;
|
||||
}
|
||||
current_request->set_measurements(measurements) ;
|
||||
|
||||
// Calibration request?
|
||||
|
|
|
@ -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<string> &media_names =
|
||||
Configuration::string_vector_value("data-input.mobile-medium") ;
|
||||
|
||||
for (vector<string>::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 *** */
|
||||
|
||||
|
||||
|
@ -193,27 +240,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<CalibrationRequest*>(
|
||||
const_cast<Request*>(&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() ;
|
||||
}
|
||||
|
|
|
@ -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) ;
|
||||
|
@ -24,8 +28,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) ;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "inputudpsocket.hh"
|
||||
#include "posexcept.hh"
|
||||
#include "stock.hh"
|
||||
#include "configuration.hh"
|
||||
|
||||
#include <owlps.h>
|
||||
|
||||
|
@ -106,8 +107,14 @@ 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) ;
|
||||
|
||||
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) ;
|
||||
|
||||
|
@ -135,20 +142,50 @@ 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) ;
|
||||
|
||||
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<int_fast8_t>
|
||||
(request_info.antenna_signal_dbm)) ;
|
||||
}
|
||||
|
||||
if (measurements.empty())
|
||||
{
|
||||
current_request->clear() ;
|
||||
return *current_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<AccessPoint&>(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() ;
|
||||
|
||||
// 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,
|
||||
|
|
|
@ -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) ;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef _OWLPS_POSITIONING_MOBILESREADERCSV_HH_
|
||||
#define _OWLPS_POSITIONING_MOBILESREADERCSV_HH_
|
||||
|
||||
class Point3D ;
|
||||
|
||||
#include "csvfilereader.hh"
|
||||
|
||||
#include <string>
|
||||
|
||||
/// 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_
|
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "outputterminal.hh"
|
||||
#include "outputcsv.hh"
|
||||
#include "outputudpsocket.hh"
|
||||
#include "outputtcpsocketevaal.hh"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -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,27 @@ 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(
|
||||
Configuration::string_value("output.tcpevaal-host"),
|
||||
Configuration::int_value("output.tcpevaal-port"))) ;
|
||||
}
|
||||
|
||||
|
||||
void Output::write(const ResultList &results) const
|
||||
{
|
||||
for (vector<OutputMedium*>::const_iterator i = output_media.begin() ;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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') ;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,189 @@
|
|||
#include "outputtcpsocketevaal.hh"
|
||||
#include "request.hh"
|
||||
#include "resultlist.hh"
|
||||
#include "area.hh"
|
||||
#include "stock.hh"
|
||||
#include "posexcept.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstdio> // For perror()
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
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 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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 = area_of_interest_number(position) ;
|
||||
|
||||
ostringstream str ;
|
||||
str
|
||||
<< "OwlPS "
|
||||
<< position.get_x() << ' '
|
||||
<< position.get_y() << ' '
|
||||
<< static_cast<uint64_t>(request_time) << ' '
|
||||
<< area_of_interest << '\n' ;
|
||||
|
||||
if (send_data(str.str()))
|
||||
acknowledge() ;
|
||||
}
|
||||
|
||||
|
||||
int OutputTCPSocketEvAAL::
|
||||
area_of_interest_number(const Point3D &position) const
|
||||
{
|
||||
const Area *area = Stock::in_which_area_is(position) ;
|
||||
if (area == NULL)
|
||||
return 0 ;
|
||||
|
||||
int aoi_number = 0 ;
|
||||
try
|
||||
{
|
||||
aoi_number = boost::lexical_cast<int>(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 ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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<ssize_t>(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 ;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
||||
#define _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
||||
|
||||
class Point3D ;
|
||||
|
||||
#include "outputmedium.hh"
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h> // <cstdint> is not C++ 98 compliant
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/// 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,
|
||||
const uint_fast16_t _remote_port) ;
|
||||
~OutputTCPSocketEvAAL(void) ;
|
||||
|
||||
/** @name Operations */
|
||||
//@{
|
||||
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) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
#endif // _OWLPS_POSITIONING_OUTPUTTCPSOCKETEVAAL_HH_
|
|
@ -1,5 +1,6 @@
|
|||
#include "outputterminal.hh"
|
||||
#include "resultlist.hh"
|
||||
#include "configuration.hh"
|
||||
|
||||
|
||||
|
||||
|
@ -12,5 +13,10 @@ 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' ;
|
||||
if (Configuration::bool_value("flush-output-files"))
|
||||
output_stream << std::flush ;
|
||||
}
|
||||
|
|
|
@ -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()) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "point3d.hh"
|
||||
#include "posutil.hh"
|
||||
#include "posexcept.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
@ -61,6 +62,33 @@ float Point3D::square_distance(const float _x,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* A, B and C are three points, A being the current Point3D (*this).
|
||||
* 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
|
||||
{
|
||||
double
|
||||
sq_ab = square_distance(b),
|
||||
sq_ac = square_distance(c),
|
||||
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) ;
|
||||
|
||||
return PosUtil::rad2deg(bac) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operators *** */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <owlps.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
|
@ -97,7 +99,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 +121,7 @@ void Positioning::loop()
|
|||
compute_error = true ;
|
||||
real_position = res.get_position() ;
|
||||
}
|
||||
|
||||
results.add(res) ;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,23 @@
|
|||
|
||||
#include <owlps.h>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace std ;
|
||||
using std::tr1::unordered_map ;
|
||||
|
||||
|
||||
|
||||
/* *** Maths *** */
|
||||
|
||||
|
||||
double PosUtil::rad2deg(const double &radians)
|
||||
{
|
||||
return radians * (180.0 / M_PI) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Measurements *** */
|
||||
|
||||
|
||||
|
@ -151,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<const uint8_t*>(&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 ;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
class Measurement ;
|
||||
|
||||
#include <boost/tr1/unordered_map.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
/// Utilitary class
|
||||
class PosUtil
|
||||
|
@ -12,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
|
||||
|
@ -29,6 +36,35 @@ 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) ;
|
||||
static std::string int_to_mac(const uint32_t source) ;
|
||||
//@}
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
/* *** 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_
|
||||
|
|
|
@ -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) ;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,26 @@ ReferencePoint::~ReferencePoint()
|
|||
/* *** Accessors *** */
|
||||
|
||||
|
||||
double ReferencePoint::
|
||||
average_measurements(const std::string &mac_transmitter) const
|
||||
{
|
||||
unordered_map<string, Measurement> measurements(
|
||||
get_all_measurements(mac_transmitter)) ;
|
||||
double avg = 0 ;
|
||||
int n_ss = 0 ;
|
||||
|
||||
for (unordered_map<string, Measurement>::const_iterator i =
|
||||
measurements.begin() ;
|
||||
i != measurements.end() ; ++i)
|
||||
{
|
||||
avg += i->second.get_average_ss() ;
|
||||
++n_ss ;
|
||||
}
|
||||
|
||||
return (avg / n_ss) ;
|
||||
}
|
||||
|
||||
|
||||
unordered_map<string, Measurement> ReferencePoint::
|
||||
get_all_measurements() const
|
||||
{
|
||||
|
@ -45,6 +65,109 @@ get_all_measurements() const
|
|||
}
|
||||
|
||||
|
||||
unordered_map<string, Measurement> ReferencePoint::
|
||||
get_all_measurements(const string &mac_transmitter) const
|
||||
{
|
||||
unordered_map<string, Measurement> all ;
|
||||
vector<CalibrationRequest*> requests_trx(
|
||||
get_requests(mac_transmitter)) ;
|
||||
|
||||
for (vector<CalibrationRequest*>::const_iterator i =
|
||||
requests_trx.begin() ;
|
||||
i != requests_trx.end() ; ++i)
|
||||
{
|
||||
unordered_map<string, Measurement> measurements =
|
||||
(*i)->get_measurements() ;
|
||||
for (unordered_map<string, Measurement>::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<CalibrationRequest*> ReferencePoint::
|
||||
get_requests(const string &mac_transmitter) const
|
||||
{
|
||||
vector<CalibrationRequest*> res ;
|
||||
|
||||
for (vector<CalibrationRequest*>::const_iterator i = requests.begin() ;
|
||||
i != requests.end() ; ++i)
|
||||
if ((*i)->get_mobile()->get_mac_addr() == mac_transmitter)
|
||||
res.push_back(*i) ;
|
||||
|
||||
return res ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Note that the requests pointed by the elements of #requests are
|
||||
* actually deleted from the Stock.
|
||||
*/
|
||||
void ReferencePoint::delete_requests()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
int stock_nb_requests = Stock::nb_calibration_requests() ;
|
||||
#endif // NDEBUG
|
||||
|
||||
for (vector<CalibrationRequest*>::iterator r = requests.begin() ;
|
||||
r != requests.end() ; ++r)
|
||||
Stock::delete_calibration_request(**r) ;
|
||||
|
||||
assert(Stock::nb_calibration_requests() ==
|
||||
stock_nb_requests - requests.size()) ;
|
||||
|
||||
requests.clear() ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
unsigned int nb_requests = requests.size() ;
|
||||
vector<CalibrationRequest*>::iterator r = requests.begin() ;
|
||||
while (r != requests.end())
|
||||
{
|
||||
assert(*r) ;
|
||||
unordered_map<std::string, AccessPoint>::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 still associated with an AP
|
||||
{
|
||||
++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 nb_requests != requests.size() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Operations *** */
|
||||
|
||||
|
@ -115,6 +238,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
|
||||
|
@ -130,8 +254,8 @@ 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() ;
|
||||
assert((*request)->get_mobile()) ;
|
||||
float mobile_gain =
|
||||
(*request)->get_mobile()->get_antenna_gain() ;
|
||||
friis_idx_sum +=
|
||||
|
|
|
@ -25,6 +25,12 @@ protected:
|
|||
//@{
|
||||
std::tr1::unordered_map<std::string, Measurement>
|
||||
get_all_measurements(void) const ;
|
||||
/// Returns all the measurements sent by the given mobile
|
||||
std::tr1::unordered_map<std::string, Measurement>
|
||||
get_all_measurements(const std::string &mac_transmitter) const ;
|
||||
/// Returns the calibration requests sent by the given mobile
|
||||
const std::vector<CalibrationRequest*> get_requests(
|
||||
const std::string &mac_transmitter) const ;
|
||||
//@}
|
||||
|
||||
public:
|
||||
|
@ -42,12 +48,17 @@ public:
|
|||
/** @name Read accessors */
|
||||
//@{
|
||||
const std::vector<CalibrationRequest*>& get_requests(void) const ;
|
||||
double average_measurements(const std::string &mac_transmitter) const ;
|
||||
//@}
|
||||
|
||||
/** @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
|
||||
bool delete_generated_requests(void) ;
|
||||
//@}
|
||||
|
||||
/** @name Operations */
|
||||
|
@ -93,16 +104,16 @@ std::vector<CalibrationRequest*>& 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<CalibrationRequest*>(cm)) ;
|
||||
if (r != NULL)
|
||||
requests.push_back(const_cast<CalibrationRequest*>(r)) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "result.hh"
|
||||
#include "request.hh"
|
||||
#include "area.hh"
|
||||
#include "stock.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
@ -10,15 +12,31 @@ 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) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** 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 *** */
|
||||
|
||||
|
||||
|
@ -37,6 +55,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 +67,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 ;
|
||||
|
@ -79,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 ;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _OWLPS_POSITIONING_RESULT_HH_
|
||||
#define _OWLPS_POSITIONING_RESULT_HH_
|
||||
|
||||
class Request ;
|
||||
|
||||
#include "point3d.hh"
|
||||
|
||||
#include <string>
|
||||
|
@ -9,28 +11,35 @@
|
|||
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 ;
|
||||
std::string in_which_area(void) const ;
|
||||
//@}
|
||||
|
||||
/** @name Write accessors */
|
||||
|
@ -60,6 +69,12 @@ public:
|
|||
/* *** Read accessors *** */
|
||||
|
||||
|
||||
inline const Request* Result::get_request() const
|
||||
{
|
||||
return request ;
|
||||
}
|
||||
|
||||
|
||||
inline const std::string& Result::get_algorithm() const
|
||||
{
|
||||
return algorithm ;
|
||||
|
|
|
@ -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<Result>& 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 ;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "stock.hh"
|
||||
#include "configuration.hh"
|
||||
#include "posexcept.hh"
|
||||
#include "area.hh"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std ;
|
||||
using std::tr1::unordered_map ;
|
||||
|
@ -15,6 +19,8 @@ unordered_map<Point3D, Waypoint> Stock::waypoints ;
|
|||
|
||||
unordered_map<string, Mobile> Stock::mobiles ;
|
||||
|
||||
uint32_t Stock::nb_virtual_mobiles = 0 ;
|
||||
|
||||
unordered_map<string, AccessPoint> Stock::aps ;
|
||||
|
||||
unordered_set<ReferencePoint,
|
||||
|
@ -77,6 +83,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<string, Building>::const_iterator
|
||||
b = buildings.begin() ; b != buildings.end() ; ++b)
|
||||
{
|
||||
const unordered_map<string, Area*> &areas = b->second.get_areas() ;
|
||||
for (unordered_map<string, Area*>::const_iterator
|
||||
a = areas.begin() ; a != areas.end() ; ++a)
|
||||
if (a->second->contains_point(point))
|
||||
return a->second ;
|
||||
}
|
||||
|
||||
return NULL ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Waypoint operations *** */
|
||||
|
||||
|
@ -115,6 +141,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<string, Mobile>::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.
|
||||
|
@ -147,10 +186,38 @@ 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<string, Mobile>::const_iterator i = mobiles.find(mac) ;
|
||||
if (i != mobiles.end())
|
||||
return i->second ;
|
||||
|
||||
mobiles[mac] = source ;
|
||||
return mobiles[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<string, AccessPoint>::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.
|
||||
|
@ -179,6 +246,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 ;
|
||||
}
|
||||
|
||||
|
@ -239,10 +312,62 @@ 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) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @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<string, AccessPoint>::const_iterator ap =
|
||||
aps.begin() ; ap != aps.end() ; ++ap)
|
||||
if (ap->second.get_coordinates() == coord)
|
||||
return true ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** ReferencePoint operations *** */
|
||||
|
||||
|
||||
bool Stock::reference_point_exists(const ReferencePoint &point)
|
||||
{
|
||||
unordered_set<ReferencePoint>::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.
|
||||
* @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<ReferencePoint>::const_iterator i =
|
||||
reference_points.find(point) ;
|
||||
if (i != reference_points.end())
|
||||
return *i ;
|
||||
throw element_not_found("No ReferencePoint with coordinates " +
|
||||
static_cast<string>(point) + "!") ;
|
||||
}
|
||||
|
||||
|
||||
const ReferencePoint& Stock::
|
||||
find_create_reference_point(const ReferencePoint &point)
|
||||
{
|
||||
|
@ -262,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<ReferencePoint>::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<ReferencePoint>::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)
|
||||
{
|
||||
|
@ -281,10 +424,258 @@ 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<ReferencePoint>::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_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_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) ;
|
||||
|
||||
// If the point is the coordinates of an existing AP, we don't
|
||||
// need to generate it
|
||||
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<string, Measurement> measurements ;
|
||||
|
||||
/* Prepare the virtual mobile */
|
||||
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
|
||||
// The gain and trx power of the mobile will be the average of
|
||||
// those of all the known APs (could be better, probably)
|
||||
double vmob_gain = 0 ;
|
||||
double vmob_pow = 0 ;
|
||||
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
rx = aps.begin() ; rx != aps.end() ; ++rx)
|
||||
{
|
||||
/* Update the mobile's attributes */
|
||||
vmob_gain += rx->second.get_antenna_gain() / aps.size() ;
|
||||
vmob_pow += rx->second.get_trx_power() / aps.size() ;
|
||||
|
||||
/* Choose the 2 nearest APs in angle */
|
||||
const Point3D &rx_coord =
|
||||
rx->second.get_coordinates() ;
|
||||
multimap<double,
|
||||
unordered_map<string, AccessPoint>::const_iterator>
|
||||
sorted_angles ;
|
||||
for (unordered_map<string, AccessPoint>::const_iterator
|
||||
ref = aps.begin() ; ref != aps.end() ; ++ref)
|
||||
{
|
||||
if (ref == rx)
|
||||
continue ;
|
||||
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<double,
|
||||
unordered_map<string, AccessPoint>::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<double,
|
||||
unordered_map<string, AccessPoint>::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<double>(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 ;
|
||||
|
||||
/* Create the measurement, add it to the list */
|
||||
Measurement m(&rx->second) ;
|
||||
m.add_ss(rx_ss) ;
|
||||
measurements[rx->second.get_mac_addr()] = m ;
|
||||
}
|
||||
|
||||
/* Create the virtual mobile */
|
||||
Mobile vmob("", vmob_mac, vmob_gain, vmob_pow) ;
|
||||
const Mobile &mobile = find_create_mobile(vmob) ;
|
||||
|
||||
/* Create the calibration request */
|
||||
CalibrationRequest cr(OWL_REQUEST_GENERATED) ;
|
||||
cr.set_time_sent(time_sent) ;
|
||||
cr.set_mobile(&mobile) ;
|
||||
cr.set_measurements(measurements) ;
|
||||
cr.set_reference_point(¤t_rp) ;
|
||||
|
||||
store_calibration_request(cr) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** CalibrationRequest operations *** */
|
||||
|
||||
|
||||
/**
|
||||
* @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 ;
|
||||
}
|
||||
|
||||
|
||||
void Stock::
|
||||
delete_calibration_request(const CalibrationRequest &request)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
unordered_set<CalibrationRequest>::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) ;
|
||||
}
|
||||
|
||||
|
||||
const CalibrationRequest& Stock::
|
||||
find_create_calibration_request(const CalibrationRequest &request)
|
||||
{
|
||||
|
@ -302,13 +693,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<CalibrationRequest>::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<CalibrationRequest>::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)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,9 @@ private:
|
|||
/** The string key of the map is the Mobile MAC address. */
|
||||
static std::tr1::unordered_map<std::string, Mobile> 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<std::string, AccessPoint> aps ;
|
||||
|
@ -47,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 */
|
||||
|
@ -68,10 +73,17 @@ public:
|
|||
|
||||
/** @name Mobile operations */
|
||||
//@{
|
||||
/// 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) ;
|
||||
/// 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) ;
|
||||
|
@ -81,24 +93,40 @@ 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<std::string, AccessPoint>& 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
|
||||
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) ;
|
||||
/// 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 */
|
||||
//@{
|
||||
/// 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) ;
|
||||
/// Searches for a ReferencePoint and adds it if it does not exist
|
||||
static const ReferencePoint&
|
||||
find_create_reference_point(const ReferencePoint &point) ;
|
||||
|
@ -106,12 +134,22 @@ 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 */
|
||||
//@{
|
||||
/// 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 const CalibrationRequest& 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) ;
|
||||
|
@ -161,6 +199,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
|
||||
|
@ -183,6 +227,13 @@ inline unsigned int Stock::nb_aps()
|
|||
}
|
||||
|
||||
|
||||
inline
|
||||
std::tr1::unordered_map<std::string, AccessPoint>& Stock::get_aps()
|
||||
{
|
||||
return aps ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the AccessPoint corresponding to \em mac does not exist, it is
|
||||
* created.
|
||||
|
|
|
@ -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 *** */
|
||||
|
@ -106,6 +109,13 @@ void UserInterface::fill_data_input_options()
|
|||
("data-input.ap-csv-file", po::value<string>(),
|
||||
"CSV file to use for access points input (when"
|
||||
" data-input.ap-medium = CSV).")
|
||||
("data-input.mobile-medium", po::value< vector<string> >()
|
||||
->composing(),
|
||||
"Medium from which mobiles are read. You can specify this"
|
||||
" option more than once. Allowed: CSV.")
|
||||
("data-input.mobile-csv-file", po::value<string>(),
|
||||
"CSV file to use for mobiles input (when"
|
||||
" data-input.mobile-medium = CSV).")
|
||||
("data-input.topology-medium,T", po::value< vector<string> >()
|
||||
->composing(),
|
||||
"Medium from which topology (buildings, areas and waypoints) is"
|
||||
|
@ -186,6 +196,49 @@ 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<bool>()->default_value(false),
|
||||
"Generate reference points from the (auto)calibration requests"
|
||||
" received.")
|
||||
("positioning.generated-meshing-grain-x",
|
||||
po::value<float>()->default_value(0.5),
|
||||
"When generating reference points, this distance (in meters) will"
|
||||
" separate each point to the next in X.")
|
||||
("positioning.generated-meshing-grain-y",
|
||||
po::value<float>()->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<bool>()->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<bool>()->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.position-calibration-requests",
|
||||
po::value<bool>()->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<bool>()->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<bool>()->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).")
|
||||
("positioning.accept-new-mobiles",
|
||||
po::value<bool>()->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) ;
|
||||
|
@ -199,8 +252,9 @@ void UserInterface::fill_output_options()
|
|||
options.add_options()
|
||||
("output.medium,O", po::value< vector<string> >()->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<string>(),
|
||||
"CSV file to use for output (when output.medium = CSV).")
|
||||
("output.udp-host", po::value<string>(),
|
||||
|
@ -208,6 +262,12 @@ void UserInterface::fill_output_options()
|
|||
("output.udp-port", po::value<int>()
|
||||
->default_value(MOBILE_DEFAULT_PORT),
|
||||
"Port on which the UDP data is sent (when output.medium = UDP).")
|
||||
("output.tcpevaal-host", po::value<string>()
|
||||
->default_value(DEFAULT_TCPEVAAL_HOST),
|
||||
"Host to which the TCP data is sent (when output.medium = TCPEvAAL).")
|
||||
("output.tcpevaal-port", po::value<int>()
|
||||
->default_value(DEFAULT_TCPEVAAL_PORT),
|
||||
"Port on which the TCP data is sent (when output.medium = TCPEvAAL).")
|
||||
;
|
||||
|
||||
file_options->add(options) ;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef _OWLPS_POSITIONING_WIFIDEVICE_HH_
|
||||
#define _OWLPS_POSITIONING_WIFIDEVICE_HH_
|
||||
|
||||
#include "posutil.hh"
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
|
||||
|
@ -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 ;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue