Merge branch 'dev' into dev-drone

Update string2data() to the new CSV format (and clean it a bit).
This commit is contained in:
Matteo Cypriani 2011-08-18 13:13:06 +02:00
commit b62987efb0
70 changed files with 1090 additions and 901 deletions

65
TODO
View File

@ -68,4 +68,67 @@
* Positioning
- Has its own fat TODO file, which I could merge in here.
- Known bugs
° Cannot compute the error (Real) with autocalibration requests.
- Algorithms
° 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::generate_reference_point() into several functions.
° 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
° When reading the APs, add them to the mobiles' list (or another
way to be able to have a single entry for an AP).
° 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.
° Pre-allocate vectors' memory with reserve().
"C++ en action", p. 217.
° Copy of containers to streams (in some operator<<() for
instance).
"C++ en action", p. 275.
° Review all the classes to respect principles exposed in "Coder
proprement", chapter 6, p. 103: do implement accessors for each
class attribute, etc.
- Unit tests
° Update tests (currently unmaintained).
° Unfinished tests:
. InputDataReader
. Input
. 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.

View File

@ -66,3 +66,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -67,3 +67,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -121,3 +121,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -123,3 +123,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -157,83 +157,6 @@ typedef struct _owl_autocalibration_order
#define OWL_80211_HZ_CHANNEL_14 2477000000ul
/* Packet header sizes (in bytes) */
#define IEEE80211_HEADER_SIZE_DATA 24 // Header size for a Data frame
#define LLC_HEADER_SIZE 8
/* IEEE 802.11 frame types */
// Beacon (TODO: convert to mask)
#define RAW_PACKET_TYPE_BEACON 0x80
// Data frame
#define FRAME_TYPE_DATA_MASK 0x08
#define IS_DATA_FRAME(FC1) \
(((FC1) & FRAME_TYPE_DATA_MASK) == FRAME_TYPE_DATA_MASK)
// QoS Data frame
#define FRAME_SUBTYPE_QOS_MASK 0x80
#define DATA_FRAME_IS_QOS(FC1) \
(((FC1) & FRAME_SUBTYPE_QOS_MASK) == FRAME_SUBTYPE_QOS_MASK)
// To/From DS
#define FRAME_FROM_STA_MASK 0x02
#define IS_FRAME_FROM_STA(FC2) \
(((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK)
/* Positions of the radiotap header fixed fields (in bytes) */
#define RTAP_P_HREVISION 0 // Header revision
#define RTAP_P_HPAD 1 // Header pad
#define RTAP_P_HLENGTH 2 // Header length
#define RTAP_P_PRESENTFLAGS 4 // Present flags
/* Radiotap field lengths (in bytes) */
#define RTAP_L_HREVISION 1 // Header revision
#define RTAP_L_HPAD 1 // Header pad
#define RTAP_L_HLENGTH 2 // Header length
#define RTAP_L_PRESENTFLAGS 4 // Present flags
#define RTAP_L_MACTS 8 // MAC timestamp (Time Synchronization Function Timer)
#define RTAP_L_FLAGS 1 // autre champ de flags
#define RTAP_L_RATE 1 // Data rate
#define RTAP_L_CHANNEL 2 // Channel frequency
#define RTAP_L_CHANNELTYPE 2 // Channel type
#define RTAP_L_ANTENNASIGNALDBM 1 // SSI signal (dBm)
#define RTAP_L_ANTENNANOISEDBM 1 // SSI noise (dBm)
#define RTAP_L_ANTENNA 1 // Antenna number
#define RTAP_L_FHSS 2 // Hop set and pattern for Frequency-Hopping Spread Spectrum
#define RTAP_L_LOCKQUALITY 2 // Signal quality
#define RTAP_L_TXATTENUATION 2 // Transmit power from max power
#define RTAP_L_TXATTENUATIONDB 2 // Idem (dB)
#define RTAP_L_TXATTENUATIONDBM 1 // Idem (dBm)
#define RTAP_L_ANTENNASIGNALDB 1 // SSI signal (dB)
#define RTAP_L_ANTENNANOISEDB 1 // SSI noise (dB)
#define RTAP_L_FCS 4 // Frame Check Sequence
//#define RTAP_L_CHANNELP // Extended channel info (not implemented)
//#define RTAP_L_EXT // Extension aux Present flags (not emplemented)
/* Positions in 'Present flags' (and present fields 'check' array) */
#define RTAP_MACTS 0
#define RTAP_FLAGS 1
#define RTAP_RATE 2
#define RTAP_CHANNEL 3 // and RTAP_CHANNELTYPE
#define RTAP_FHSS 4
#define RTAP_ANTENNASIGNALDBM 5
#define RTAP_ANTENNANOISEDBM 6
#define RTAP_LOCKQUALITY 7
#define RTAP_TXATTENUATION 8
#define RTAP_TXATTENUATIONDB 9
#define RTAP_TXATTENUATIONDBM 10
#define RTAP_ANTENNA 11
#define RTAP_ANTENNASIGNALDB 12
#define RTAP_ANTENNANOISEDB 13
#define RTAP_FCS 14
//#define RTAP_CHANNELP 18
//#define RTAP_EXT 31
/* Misc. */
// Length of a MAC address in string format (including '\0')
#define OWL_ETHER_ADDR_STRLEN 18
@ -245,10 +168,6 @@ extern owl_bool owl_run ;
/* Function error codes */
#define ERR_SETTING_MODE 101
#define ERR_SETTING_CHANNEL 102
#define ERR_READING_CHANNEL 103
#define ERR_READING_MODE 104
#define ERR_BAD_SIGNAL 111

View File

@ -605,7 +605,7 @@ void* monitor_requests(void *NULL_value)
request_info_ptr = request_ptr->info ;
while (request_info_ptr != NULL)
{
request.nb_info++;
++request.nb_info ;
request_info_ptr = request_info_ptr->next ;
}
// Endianess conversions:

View File

@ -798,28 +798,29 @@ void* receive_position(void* NULL_value)
}
/* Split the string received from OwlPS Positioning and store the fields
* in a result structure.
*
* Handled CSV format:
* Mobile_MAC;Request_type;Request_timestamp;Algorithm;X;Y;Z;Error;Area
* The Request_timestamp format is: seconds.nanoseconds
*/
void string2data(char* string_data)
{
/*Découpage de la chaine de caractère reçu du serveur de positionnement
sous forme de addrMAC;TypeRequete;Timestamp1.Timestamp2;Algo;X;Y;Z
en variables séparées
*/
char *mac = NULL ;
char *ptr = NULL ;
char *delims = ";" ;
const char delims[] = ";" ;
int type_req = 0 ;
int count_algo= 0 ;
int count_print = 0 ;
int onetime = 0 ;
int error = 0 ;
owl_bool error_present = FALSE ;
while(onetime<1)
{
//Lecture Adresse Mac
// Mobile MAC address
ptr = strtok(string_data, delims) ;
if(ptr==NULL)
{
@ -828,7 +829,7 @@ void string2data(char* string_data)
}
mac = ptr ;
//Lecture Type Request
// Request type
ptr = strtok(NULL, delims) ;
if (ptr==NULL)
{
@ -837,7 +838,7 @@ void string2data(char* string_data)
}
type_req = atoi(ptr) ;
//Lecture TimeStamp1
// Timestamp (seconds)
ptr = strtok(NULL, ".") ;
if (ptr==NULL)
{
@ -846,7 +847,7 @@ void string2data(char* string_data)
}
sscanf(ptr, "%ld", &timestamp.tv_sec) ;
//Lecture TimeStamp2
// Timestamp (nanoseconds)
ptr = strtok(NULL, ";") ;
if (ptr==NULL)
{
@ -860,14 +861,15 @@ void string2data(char* string_data)
while(run)
{
//Lecture de l'algorythme utilisé
// Algorithm name
ptr = strtok(NULL, delims) ;
if(ptr==NULL) break ;
sscanf(ptr, "%s", results[count_algo].algo) ;
if (ptr == NULL)
break ;
strncpy(results[count_algo].algo, ptr, ALGO_STRLEN) ;
if(!strcmp(results[count_algo].algo,"Real"))
error=1;
error_present = TRUE ;
//Lecture du point X
// X coordinate
ptr = strtok(NULL, delims) ;
if(ptr==NULL)
{
@ -885,7 +887,7 @@ void string2data(char* string_data)
}
results[count_algo].x = atof(ptr) ;
//Lecture du point Y
// Y coordinate
ptr = strtok(NULL, delims) ;
if(ptr==NULL)
{
@ -903,7 +905,7 @@ void string2data(char* string_data)
}
results[count_algo].y = atof(ptr) ;
//Lecture du point Z
// Z coordinate
ptr = strtok(NULL, delims) ;
if(ptr==NULL)
{
@ -914,15 +916,16 @@ void string2data(char* string_data)
}
else
{
perror ("algo");
print_error("algo") ;
count_algo--;
break ;
}
}
results[count_algo].z = atof(ptr) ;
if(error==1)
// Distance error
if (error_present)
{
//Lecture du message Error
ptr = strtok(NULL, delims) ;
if(ptr==NULL)
{
@ -938,52 +941,50 @@ void string2data(char* string_data)
break ;
}
}
results[count_algo].check = ptr ;
//Lecture valeur Error
ptr = strtok(NULL, delims) ;
if(ptr==NULL)
{
if(count_algo==0)
{
print_error ("trame");
break ;
}
else
{
perror ("algo");
count_algo--;
break ;
}
}
results[count_algo].err = atof(ptr) ;
++count_algo ;
results[count_algo].error = atof(ptr) ;
}
++count_algo ;
else
++count_algo ;
// Area name
ptr = strtok(NULL, delims) ;
if (ptr == NULL)
{
if (count_algo == 0)
{
print_error("trame") ;
break ;
}
else
{
print_error("algo") ;
count_algo-- ;
break ;
}
}
strncpy(results[count_algo].area, ptr, AREA_STRLEN) ;
}
for (count_print = 0 ; count_print < count_algo ; ++count_print)
printf("\n----------------\n"
" Adresse Mac : %s\n"
" Type de requete : %d\n"
" Timestamp : %ld.%ld\n"
" Algo : %s\n"
" X : %f\n "
" Y : %f\n"
" Z : %f\n"
" Mobile's MAC address: %s\n"
" Request type: %d\n"
" Timestamp: %ld.%ld\n"
" Algorithm: %s\n"
" X: %f\n"
" Y: %f\n"
" Z: %f\n"
" Distance error: %f\n"
" Area: %s\n"
"------------------\n",
mac,
type_req,
timestamp.tv_sec,
timestamp.tv_nsec,
timestamp.tv_sec, timestamp.tv_nsec,
results[count_print].algo,
results[count_print].x,
results[count_print].y,
results[count_print].z) ;
results[count_print].z,
results[count_print].error,
results[count_print].area) ;
}

View File

@ -15,8 +15,9 @@
#define DEFAULT_DELAY_CALIB 50000 // Calibration request
#define DEFAULT_DELAY_NORMAL 25000 // Localisation request
/* Maximum length of the algorithm name */
/* Maximum length of the algorithm & area names */
#define ALGO_STRLEN 15
#define AREA_STRLEN 50
/* GPS inputs */
#define SEPARATOR ','
@ -38,15 +39,15 @@
#define ERR_BAD_USAGE 1 // Bad program call (bad number of arguments)
/* Received result */
/* Result from OwlPS Positioning (parsed string structure) */
typedef struct _result
{
char algo[ALGO_STRLEN];
float x;
float y;
float z;
char *check;
float err;
float error ;
char area[AREA_STRLEN] ;
} result ;
typedef struct _gps

View File

@ -99,3 +99,8 @@ purge : clean
help :
@make -f Makefile_atheros help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -114,3 +114,8 @@ $(TARGET).semistatic (version sans lien dynamique vers libowlps)."
@echo
@echo "Note : l'installation se fait dans l'arborescence $(PREFIX). \
Modifiez la variable PREFIX du Makefile pour changer ce comportement."
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -157,7 +157,7 @@ void parse_main_options(int argc, char **argv)
// Take the optind value:
options.flood_delay =
strtoul(argv[optind], NULL, 0) ;
optind++ ;
++optind ;
}
}
break ;
@ -185,7 +185,7 @@ void parse_main_options(int argc, char **argv)
// Take the optind value:
options.listening_port =
strtoul(argv[optind], NULL, 0) ;
optind++ ;
++optind ;
}
}
break ;

View File

@ -101,3 +101,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -97,3 +97,8 @@ purge : clean
help :
@make help
# Local Variables: *
# mode: makefile-gmake *
# End: *

View File

@ -71,11 +71,89 @@ enum {MODE_ACTIVE = 'a', MODE_PASSIVE = 'p', MODE_MIXED = 'm'} ;
#define VERBOSE_CHATTERBOX GET_VERBOSE() >= 3
/* Packet header sizes (in bytes) */
#define IEEE80211_HEADER_SIZE_DATA 24 // Header size for a Data frame
#define LLC_HEADER_SIZE 8
/* IEEE 802.11 frame types */
// Beacon (TODO: convert to mask)
#define RAW_PACKET_TYPE_BEACON 0x80
// Data frame
#define FRAME_TYPE_DATA_MASK 0x08
#define IS_DATA_FRAME(FC1) \
(((FC1) & FRAME_TYPE_DATA_MASK) == FRAME_TYPE_DATA_MASK)
// QoS Data frame
#define FRAME_SUBTYPE_QOS_MASK 0x80
#define DATA_FRAME_IS_QOS(FC1) \
(((FC1) & FRAME_SUBTYPE_QOS_MASK) == FRAME_SUBTYPE_QOS_MASK)
// To/From DS
#define FRAME_FROM_STA_MASK 0x02
#define IS_FRAME_FROM_STA(FC2) \
(((FC2) & FRAME_FROM_STA_MASK) != FRAME_FROM_STA_MASK)
/* Positions of the radiotap header fixed fields (in bytes) */
#define RTAP_P_HREVISION 0 // Header revision
#define RTAP_P_HPAD 1 // Header pad
#define RTAP_P_HLENGTH 2 // Header length
#define RTAP_P_PRESENTFLAGS 4 // Present flags
/* Radiotap field lengths (in bytes) */
#define RTAP_L_HREVISION 1 // Header revision
#define RTAP_L_HPAD 1 // Header pad
#define RTAP_L_HLENGTH 2 // Header length
#define RTAP_L_PRESENTFLAGS 4 // Present flags
#define RTAP_L_MACTS 8 // MAC timestamp (Time Synchronization Function Timer)
#define RTAP_L_FLAGS 1 // autre champ de flags
#define RTAP_L_RATE 1 // Data rate
#define RTAP_L_CHANNEL 2 // Channel frequency
#define RTAP_L_CHANNELTYPE 2 // Channel type
#define RTAP_L_ANTENNASIGNALDBM 1 // SSI signal (dBm)
#define RTAP_L_ANTENNANOISEDBM 1 // SSI noise (dBm)
#define RTAP_L_ANTENNA 1 // Antenna number
#define RTAP_L_FHSS 2 // Hop set and pattern for Frequency-Hopping Spread Spectrum
#define RTAP_L_LOCKQUALITY 2 // Signal quality
#define RTAP_L_TXATTENUATION 2 // Transmit power from max power
#define RTAP_L_TXATTENUATIONDB 2 // Idem (dB)
#define RTAP_L_TXATTENUATIONDBM 1 // Idem (dBm)
#define RTAP_L_ANTENNASIGNALDB 1 // SSI signal (dB)
#define RTAP_L_ANTENNANOISEDB 1 // SSI noise (dB)
#define RTAP_L_FCS 4 // Frame Check Sequence
//#define RTAP_L_CHANNELP // Extended channel info (not implemented)
//#define RTAP_L_EXT // Present flags' extension (not emplemented)
/* Positions in 'Present flags' (and present fields 'check' array) */
#define RTAP_MACTS 0
#define RTAP_FLAGS 1
#define RTAP_RATE 2
#define RTAP_CHANNEL 3 // and RTAP_CHANNELTYPE
#define RTAP_FHSS 4
#define RTAP_ANTENNASIGNALDBM 5
#define RTAP_ANTENNANOISEDBM 6
#define RTAP_LOCKQUALITY 7
#define RTAP_TXATTENUATION 8
#define RTAP_TXATTENUATIONDB 9
#define RTAP_TXATTENUATIONDBM 10
#define RTAP_ANTENNA 11
#define RTAP_ANTENNASIGNALDB 12
#define RTAP_ANTENNANOISEDB 13
#define RTAP_FCS 14
//#define RTAP_CHANNELP 18
//#define RTAP_EXT 31
/* Error codes */
#define ERR_OPENING_IFACE 2 // Error when opening capture interface
#define ERR_BAD_USAGE 3 // Bad program call
#define ERR_PARSING_CONFIG_FILE 4 // Error reading the configuration file
#define ERR_CREATING_THREAD 6 // Error creating a thread
#define ERR_SETTING_MODE 101
#define ERR_READING_MODE 104
/* Function headers */
@ -98,6 +176,11 @@ int iface_mode_monitor(const char *const iface) ;
int capture(void) ;
void read_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet) ;
void extract_calibration_data(const u_char *packet,
owl_captured_request *request) ;
void extract_radiotap_data(const u_char *packet,
owl_captured_request *request,
owl_bool rtap_fields[15]) ;
void get_mac_addr(char *eth, uint8_t mac_bytes[ETHER_ADDR_LEN]) ;
void get_ip_addr(char *eth, char *ip_bytes) ;

View File

@ -770,12 +770,9 @@ int capture()
void read_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet)
{
uint16_t rtap_bytes ; // Received data size
uint32_t rtap_presentflags ;
uint_fast16_t rtap_position ;
owl_captured_request request ; // Message to send to the aggregator
ssize_t nsent ; // sendto return value
owl_bool check[15] ; // Present flags
uint16_t rtap_bytes ; // Radiotap header size
owl_bool rtap_fields[15] ; // Present flags
uint8_t raw_packet_fc1 ; // First byte of the received frame's FC
uint8_t raw_packet_fc2 ; // Second byte of the received frame's FC
uint8_t raw_packet_flags ; // IEEE 802.11 header flags
@ -790,7 +787,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
owl_bool is_explicit_packet = TRUE ; // Is the packet an explicit request?
// Is the packet an autocalibration positioning request?
owl_bool uses_autocalibration_request_port = FALSE ;
int i ; // Iterator
ssize_t nsent ; // sendto return value
// Blank the request:
memset(&request, 0, sizeof(request)) ;
@ -909,21 +906,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
case OWL_REQUEST_CALIBRATION :
if (VERBOSE_INFO)
printf("\nExplicit calibration packet received.\n") ;
request.direction =
packet[rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE
+ sizeof(struct iphdr) + sizeof(struct udphdr) + 9];
memcpy(&request.x_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 10], sizeof(float)) ;
memcpy(&request.y_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 14], sizeof(float)) ;
memcpy(&request.z_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 18], sizeof(float)) ;
extract_calibration_data(&packet[rtap_bytes +
ieee80211_header_size +
LLC_HEADER_SIZE
+ sizeof(struct iphdr) +
sizeof(struct udphdr) + 9],
&request) ;
break ;
case OWL_REQUEST_AUTOCALIBRATION :
@ -934,21 +922,12 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
printf(".. on the wrong port!") ;
putchar('\n') ;
}
request.direction =
packet[rtap_bytes + ieee80211_header_size + LLC_HEADER_SIZE
+ sizeof(struct iphdr) + sizeof(struct udphdr) + 9];
memcpy(&request.x_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 10], sizeof(float)) ;
memcpy(&request.y_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 14], sizeof(float)) ;
memcpy(&request.z_position,
&packet[rtap_bytes + ieee80211_header_size
+ LLC_HEADER_SIZE + sizeof(struct iphdr)
+ sizeof(struct udphdr) + 18], sizeof(float)) ;
extract_calibration_data(&packet[rtap_bytes +
ieee80211_header_size +
LLC_HEADER_SIZE
+ sizeof(struct iphdr) +
sizeof(struct udphdr) + 9],
&request) ;
break ;
default :
@ -991,96 +970,8 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
else // Active mode, packet was not an explicit request
return ;
/* Radiotap header handling */
// Get rtap flags:
memcpy(&rtap_presentflags,
&packet[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
// Radiotap header is little-endian
rtap_presentflags = le32toh(rtap_presentflags) ;
for (i = 0 ; i < 15 ; i++) // Initialise present flags structure
check[i] = FALSE ;
rtap_position = 8 ; // Begining of the present flags determined fields
// Test the first 15 bits of the flag field in order to check their
// presence and to copy them:
for (i = 0 ; i < 15 ; i++)
{
if ((rtap_presentflags % 2) == 1)
{
switch(i)
{
case RTAP_MACTS:
check[RTAP_MACTS] = TRUE ;
rtap_position += RTAP_L_MACTS ;
break ;
case RTAP_FLAGS:
check[RTAP_FLAGS] = TRUE;
rtap_position += RTAP_L_FLAGS ;
break ;
case RTAP_RATE:
check[RTAP_RATE] = TRUE;
rtap_position += RTAP_L_RATE ;
break ;
case RTAP_CHANNEL:
rtap_position += RTAP_L_CHANNEL ;
rtap_position += RTAP_L_CHANNELTYPE ;
break ;
case RTAP_FHSS:
check[RTAP_FHSS] = TRUE;
rtap_position += RTAP_L_FHSS ;
break ;
case RTAP_ANTENNASIGNALDBM:
memcpy(&(request.antenna_signal_dbm),
&packet[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
check[RTAP_ANTENNASIGNALDBM] = TRUE;
if (VERBOSE_INFO)
printf("Antenna signal: %d dBm\n",
request.antenna_signal_dbm - 0x100);
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
break ;
case RTAP_ANTENNANOISEDBM:
check[RTAP_ANTENNANOISEDBM] = TRUE;
rtap_position += RTAP_L_ANTENNANOISEDBM ;
break ;
case RTAP_LOCKQUALITY:
check[RTAP_LOCKQUALITY] = TRUE;
rtap_position += RTAP_L_LOCKQUALITY ;
break ;
case RTAP_TXATTENUATION:
check[RTAP_TXATTENUATION] = TRUE;
rtap_position += RTAP_L_TXATTENUATION ;
break ;
case RTAP_TXATTENUATIONDB:
check[RTAP_TXATTENUATIONDB] = TRUE;
rtap_position += RTAP_L_TXATTENUATIONDB ;
break ;
case RTAP_TXATTENUATIONDBM:
check[RTAP_TXATTENUATIONDBM] = TRUE;
rtap_position += RTAP_L_TXATTENUATIONDBM ;
break ;
case RTAP_ANTENNA:
check[RTAP_ANTENNA] = TRUE;
rtap_position += RTAP_L_ANTENNA ;
break ;
case RTAP_ANTENNASIGNALDB:
check[RTAP_ANTENNASIGNALDB] = TRUE;
rtap_position += RTAP_L_ANTENNASIGNALDB ;
break ;
case RTAP_ANTENNANOISEDB:
check[RTAP_ANTENNANOISEDB] = TRUE;
rtap_position += RTAP_L_ANTENNANOISEDB ;
break ;
case RTAP_FCS:
check[RTAP_FCS] = TRUE;
rtap_position += RTAP_L_FCS ;
break ;
}
}
rtap_presentflags /= 2 ;
}
extract_radiotap_data(packet, &request, rtap_fields) ;
/* Display the packet details */
if (GET_DISPLAY_CAPTURED())
@ -1109,7 +1000,7 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
owl_mac_bytes_to_string(request.mobile_mac_addr_bytes),
request_time_str,
start_time_str,
check[RTAP_ANTENNASIGNALDBM] ?
rtap_fields[RTAP_ANTENNASIGNALDBM] ?
request.antenna_signal_dbm - 0x100 : 0,
owl_ntohf(request.x_position),
owl_ntohf(request.y_position),
@ -1132,6 +1023,126 @@ void read_packet(u_char *args, const struct pcap_pkthdr *header,
/*
* Fills 'request' with the calibration data extracted from 'packet'.
* Note: 'packet' is read from its first byte, therefore you must not
* pass the whole received packet to this function.
*/
void extract_calibration_data(const u_char *packet,
owl_captured_request *request)
{
request->direction = packet[0] ;
memcpy(&request->x_position, &packet[1], sizeof(float)) ;
memcpy(&request->y_position, &packet[4], sizeof(float)) ;
memcpy(&request->z_position, &packet[8], sizeof(float)) ;
}
/*
* Fills 'request' with the required data extracted from the Radiotap
* header of 'packet'. The elements of 'rtap_fields' are set to TRUE
* when the corresponding Radiotap flag is found in the packet.
*/
void extract_radiotap_data(const u_char *packet,
owl_captured_request *request,
owl_bool rtap_fields[15])
{
uint32_t rtap_presentflags ;
uint_fast16_t rtap_position ;
int i ; // Iterator
// Get rtap flags:
memcpy(&rtap_presentflags,
&packet[RTAP_P_PRESENTFLAGS], RTAP_L_PRESENTFLAGS) ;
// The Radiotap header is little-endian
rtap_presentflags = le32toh(rtap_presentflags) ;
for (i = 0 ; i < 15 ; ++i) // Initialise present flags structure
rtap_fields[i] = FALSE ;
rtap_position = 8 ; // Begining of the present flags determined fields
// Test the first 15 bits of the flag field in order to check their
// presence and to copy them:
for (i = 0 ; i < 15 ; ++i)
{
if ((rtap_presentflags % 2) == 1)
{
switch(i)
{
case RTAP_MACTS:
rtap_fields[RTAP_MACTS] = TRUE ;
rtap_position += RTAP_L_MACTS ;
break ;
case RTAP_FLAGS:
rtap_fields[RTAP_FLAGS] = TRUE;
rtap_position += RTAP_L_FLAGS ;
break ;
case RTAP_RATE:
rtap_fields[RTAP_RATE] = TRUE;
rtap_position += RTAP_L_RATE ;
break ;
case RTAP_CHANNEL:
rtap_position += RTAP_L_CHANNEL ;
rtap_position += RTAP_L_CHANNELTYPE ;
break ;
case RTAP_FHSS:
rtap_fields[RTAP_FHSS] = TRUE;
rtap_position += RTAP_L_FHSS ;
break ;
case RTAP_ANTENNASIGNALDBM:
memcpy(&request->antenna_signal_dbm,
&packet[rtap_position], RTAP_L_ANTENNASIGNALDBM) ;
rtap_fields[RTAP_ANTENNASIGNALDBM] = TRUE;
if (VERBOSE_INFO)
printf("Antenna signal: %d dBm\n",
request->antenna_signal_dbm - 0x100);
rtap_position += RTAP_L_ANTENNASIGNALDBM ;
break ;
case RTAP_ANTENNANOISEDBM:
rtap_fields[RTAP_ANTENNANOISEDBM] = TRUE;
rtap_position += RTAP_L_ANTENNANOISEDBM ;
break ;
case RTAP_LOCKQUALITY:
rtap_fields[RTAP_LOCKQUALITY] = TRUE;
rtap_position += RTAP_L_LOCKQUALITY ;
break ;
case RTAP_TXATTENUATION:
rtap_fields[RTAP_TXATTENUATION] = TRUE;
rtap_position += RTAP_L_TXATTENUATION ;
break ;
case RTAP_TXATTENUATIONDB:
rtap_fields[RTAP_TXATTENUATIONDB] = TRUE;
rtap_position += RTAP_L_TXATTENUATIONDB ;
break ;
case RTAP_TXATTENUATIONDBM:
rtap_fields[RTAP_TXATTENUATIONDBM] = TRUE;
rtap_position += RTAP_L_TXATTENUATIONDBM ;
break ;
case RTAP_ANTENNA:
rtap_fields[RTAP_ANTENNA] = TRUE;
rtap_position += RTAP_L_ANTENNA ;
break ;
case RTAP_ANTENNASIGNALDB:
rtap_fields[RTAP_ANTENNASIGNALDB] = TRUE;
rtap_position += RTAP_L_ANTENNASIGNALDB ;
break ;
case RTAP_ANTENNANOISEDB:
rtap_fields[RTAP_ANTENNANOISEDB] = TRUE;
rtap_position += RTAP_L_ANTENNANOISEDB ;
break ;
case RTAP_FCS:
rtap_fields[RTAP_FCS] = TRUE;
rtap_position += RTAP_L_FCS ;
break ;
}
}
rtap_presentflags /= 2 ;
}
}
/*
* Get our own MAC address and copy it to 'mac_bytes'.
*/

View File

@ -101,6 +101,7 @@ OBJ_NOTEST_LIST = \
posexcept.o \
multilaterationalgorithm.o \
cartographyalgorithm.o \
outputnetworksocket.o \
inputmedium.o
INTERFACES_LIST = \
inputlogmedium.hh \
@ -214,17 +215,24 @@ $(OBJ_DIR)/csvfilereader.o: \
$(OBJ_DIR)/textfilereader.o
$(OBJ_DIR)/textfilewriter.o: \
$(OBJ_DIR)/posexcept.o
$(OBJ_DIR)/inputmedium.o: \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/posexcept.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/inputcsv.o: \
$(OBJ_DIR)/inputmedium.o \
$(OBJ_DIR)/csvfilereader.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/inputudpsocket.o: \
$(OBJ_DIR)/inputmedium.o \
$(OBJ_DIR)/posexcept.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/calibrationrequest.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/inputlogcsv.o: \
$(SRC_DIR)/inputlogmedium.hh \
@ -246,12 +254,24 @@ $(OBJ_DIR)/outputcsv.o: \
$(OBJ_DIR)/textfilewriter.o \
$(OBJ_DIR)/resultlist.o \
$(OBJ_DIR)/result.o
$(OBJ_DIR)/outputnetworksocket.o: \
$(SRC_DIR)/outputmedium.hh \
$(OBJ_DIR)/resultlist.o \
$(OBJ_DIR)/result.o
$(OBJ_DIR)/outputudpsocket.o: \
$(SRC_DIR)/outputmedium.hh \
$(OBJ_DIR)/result.o
$(OBJ_DIR)/outputnetworksocket.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/resultlist.o \
$(OBJ_DIR)/result.o \
$(OBJ_DIR)/posexcept.o
$(OBJ_DIR)/outputtcpsocketevaal.o: \
$(SRC_DIR)/outputmedium.hh \
$(OBJ_DIR)/result.o
$(OBJ_DIR)/outputnetworksocket.o \
$(OBJ_DIR)/request.o \
$(OBJ_DIR)/resultlist.o \
$(OBJ_DIR)/result.o \
$(OBJ_DIR)/area.o \
$(OBJ_DIR)/posexcept.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/outputcsv.o: \
$(SRC_DIR)/outputmedium.hh \
$(OBJ_DIR)/result.o
@ -278,7 +298,9 @@ $(OBJ_DIR)/minmax.o: \
$(OBJ_DIR)/interlinknetworks.o: \
$(OBJ_DIR)/multilaterationalgorithm.o
$(OBJ_DIR)/fbcm.o: \
$(OBJ_DIR)/multilaterationalgorithm.o
$(OBJ_DIR)/multilaterationalgorithm.o \
$(OBJ_DIR)/configuration.o \
$(OBJ_DIR)/stock.o
$(OBJ_DIR)/frbhmbasic.o: \
$(OBJ_DIR)/radar.o \
$(OBJ_DIR)/fbcm.o

View File

@ -1,88 +0,0 @@
- Known bugs
° FBCM always gives the same result.
° Cannot compute the error (Real) with autocalibration requests.
- 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:
. InputDataReader
. Input
. 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
pointeurs.
° Compositions : devraient être représentées par des attributs
normaux.
- « C++ en action »
° Espaces de noms ? 109
° Réserver l'espace mémoire des vector avec reserve(). 217
° Copie de conteneur vers un flux (cas de certains operator<<). 275
- « Coder proprement »
° Revoir toutes les classes pour respecter si possible les
principes exposés dans le chapitre 6 (p. 103) : implanter
systématiquement des accesseurs pour tous les attributs d'une
classe expose l'implantation de la classe et rend ses attributs
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.

View File

@ -49,13 +49,16 @@ csv-file = /tmp/owlps-positioning.log
#algorithm = RADAR
#algorithm = FRBHMBasic
# Start and stop coordinates for the MinMax multilateration method.
# Coordinates of the deployment area.
# This is used to delimit the area in which reference points are
# generated (when generate-reference-points is activated), and also
# by the MinMax multilateration method.
# Since MinMax is currently the only multilateration method implemented
# in OwlPS, you should define these parameters if you use any of the
# multilateration-based algorithms (InterlinkNetworks, FBCM, FRBHM).
# They are declared as strings (X;Y;Z). Do not quote!
#minmax-start = -2;-2;0
#minmax-stop = 20;30;6
#area-start = -2;-2;0
#area-stop = 20;30;6
# With the RADAR algorithm, for a given positioning request, average
# all the calibration requests associated with a reference point before
@ -123,3 +126,16 @@ csv-file = /tmp/owlps-positioning.log
#medium = CSV
csv-file = /tmp/owlps-positioning.out
#medium = UDP
# Currently, the host must be an IP address (not a DNS name).
#udp-host =
#udp-port = 9910
# Note: you can use only one algorithm when using the TCPEvAAL output.
#medium = TCPEvAAL
# Currently, the host must be an IP address (not a DNS name).
#tcpevaal-host = 127.0.0.1
#tcpevaal-port = 4444
# vim: syntax=cfg

View File

@ -5,12 +5,17 @@
# handle it. Since none of them are currently implemented, you
# probably can save a lot of time by skipping the topology (and
# waypoints) description.
# However, you can describe areas if you want to know when the mobile
# is in a particular location. In that case be sure that the algorithm
# you use will be able to generate positions that match each described
# area (in particular, with RADAR, at least one reference point should
# be present in each area).
#
# ALSO IMPORTANT (EVEN IF YOU DON'T DESCRIBE THE TOPOLOGY):
# If you use the MinMax multilateration method, you should provide
# minmax-start and minmax-stop parameters that match the deployment
# area. That is, the cuboid formed by these two points should include
# the whole deployment area.
# If you use the MinMax multilateration method, or the autocalibration,
# you must provide area-start and area-stop options that match the
# deployment area. That is, the cuboid formed by these two points
# should include the whole deployment area.
#
# This file lists the buildings and their "homogeneous areas" (rooms).
#

Can't render this file because it contains an unexpected character in line 20 and column 43.

View File

@ -5,10 +5,22 @@ using namespace std ;
/* *** Operations *** */
double AccessPoint::friis_constant_term() const
{
double wavelength =
static_cast<double>(PosUtil::LIGHT_SPEED) / frequency ;
return antenna_gain + 20 * log10(wavelength) - 20 * log10(4 * M_PI) ;
}
/* *** Operators *** */
const AccessPoint& AccessPoint::operator=(const AccessPoint &source)
AccessPoint& AccessPoint::operator=(const AccessPoint &source)
{
if (this == &source)
return *this ;

View File

@ -67,9 +67,15 @@ public:
void set_friis_index(const float _friis_index) ;
//@}
/** @name Operations */
//@{
/// Returns the Friis formula's constant term
double friis_constant_term(void) const ;
//@}
/** @name Operators */
//@{
const AccessPoint& operator=(const AccessPoint &source) ;
AccessPoint& operator=(const AccessPoint &source) ;
bool operator==(const AccessPoint &source) const ;
bool operator!=(const AccessPoint &source) const ;
//@}

View File

@ -119,7 +119,7 @@ void Area::reorder_coordinates()
/* *** Operators *** */
const Area& Area::operator=(const Area &source)
Area& Area::operator=(const Area &source)
{
if (this == &source)
return *this ;

View File

@ -55,7 +55,7 @@ public:
/** @name Operators */
//@{
const Area& operator=(const Area &source) ;
Area& operator=(const Area &source) ;
bool operator==(const Area &source) const ;
bool operator!=(const Area &source) const ;
//@}

View File

@ -73,7 +73,7 @@ void Building::add_area(Area *&area)
/* *** Operators *** */
const Building& Building::operator=(const Building &source)
Building& Building::operator=(const Building &source)
{
if (this == &source)
return *this ;

View File

@ -48,7 +48,7 @@ public :
/** @name Operators */
//@{
const Building& operator=(const Building &source) ;
Building& operator=(const Building &source) ;
bool operator==(const Building &source) const ;
bool operator!=(const Building &source) const ;
//@}

View File

@ -54,8 +54,8 @@ void CalibrationRequest::clear()
/* *** Operators *** */
const CalibrationRequest&
CalibrationRequest::operator=(const CalibrationRequest &source)
CalibrationRequest& CalibrationRequest::
operator=(const CalibrationRequest &source)
{
if (this == &source)
return *this ;
@ -68,7 +68,8 @@ CalibrationRequest::operator=(const CalibrationRequest &source)
}
bool CalibrationRequest::operator==(const CalibrationRequest &source) const
bool CalibrationRequest::
operator==(const CalibrationRequest &source) const
{
if (this == &source)
return true ;

View File

@ -48,7 +48,7 @@ public:
/** @name Operators */
//@{
const CalibrationRequest& operator=(const CalibrationRequest &source) ;
CalibrationRequest& operator=(const CalibrationRequest &source) ;
bool operator==(const CalibrationRequest &source) const ;
bool operator!=(const CalibrationRequest &source) const ;
//@}

View File

@ -36,14 +36,14 @@ inline bool Direction::is_valid() const
/* *** Operators *** */
const Direction& Direction::operator=(const Direction &source)
Direction& Direction::operator=(const Direction &source)
{
direction = source.direction ;
return *this ;
}
const Direction& Direction::operator=(const char source)
Direction& Direction::operator=(const char source)
{
direction = source ;
assert_valid() ;

View File

@ -27,8 +27,8 @@ public:
/** @name Operators */
//@{
const Direction& operator=(const Direction &source) ;
const Direction& operator=(const char source) ;
Direction& operator=(const Direction &source) ;
Direction& operator=(const char source) ;
bool operator==(const Direction &source) const ;
bool operator!=(const Direction &source) const ;
operator bool(void) const ;

View File

@ -1,7 +1,19 @@
#include "fbcm.hh"
#include "stock.hh"
#include "configuration.hh"
Result FBCM::compute(const Request &_request)
{
// If the autocalibration is activated, we have to regenerate the
// Friis indexes each time we calculate a position
if (Configuration::bool_value("positioning.generate-reference-points"))
Stock::update_all_friis_indexes() ;
return MultilaterationAlgorithm::compute(_request) ;
}
float FBCM::estimate_distance(const Measurement &measurement)
{
double constant_term = make_constant_term(measurement) ;

View File

@ -13,7 +13,11 @@ public:
FBCM(void): PositioningAlgorithm("FBCM") {}
~FBCM(void) {}
/** @name Operations */
//@{
Result compute(const Request &_request) ;
float estimate_distance(const Measurement &measurement) ;
//@}
} ;
#endif // _OWLPS_POSITIONING_FBCM_HH_

View File

@ -17,24 +17,18 @@ using std::tr1::unordered_map ;
/**
* This function reads the next Request in the CSV input file. Blank
* lines and lines containing only spaces are skipped.
* This function fills the current Request from the CSV input file.
* Blank lines and lines containing only spaces are skipped until a line
* containing a request is found.
*
* #file should be opened before proceeding requests; otherwise,
* #current_request is \link Request::clear() cleared\endlink and a
* blank Request is returned. The file must be valid,
* semicolon-separated (\em not comma-separated).
*
* @return The read Request, or a blank Request in case of error (file
* not opened, end of file, invalid field or wrong number of fields in
* the line).
* @returns \em true if #current_request was correctly filled.
* @returns \em false in case of error (file not opened, end of file,
* invalid field or wrong number of fields in the line).
*/
const Request& InputCSV::get_next_request()
bool InputCSV::fill_current_request()
{
clear_current_request() ;
if (! file.next_line()) // End of file or error
return *current_request ;
return false ;
++current_line_nb ;
// Read Mobile MAC field
@ -43,13 +37,13 @@ const Request& InputCSV::get_next_request()
{
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read mac_mobile.\n" ;
return *current_request ;
return false ;
}
PosUtil::to_upper(mac_mobile) ;
if (! Configuration::bool_value("positioning.accept-new-mobiles") &&
! Stock::mobile_exists(mac_mobile))
return *current_request ;
return false ;
const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ;
current_request->set_mobile(&mobile) ;
@ -59,11 +53,10 @@ const Request& InputCSV::get_next_request()
uint16_t type_r ;
if (! file.read_field(type_r))
{
// Wrong number of fields: blank current request
current_request->clear() ;
// Wrong number of fields
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read type.\n" ;
return *current_request ;
return false ;
}
type = type_r ;
current_request->set_type(type) ;
@ -72,11 +65,10 @@ const Request& InputCSV::get_next_request()
Timestamp timestamp ;
if (! file.read_timestamp(timestamp))
{
// Wrong number of fields: blank current request
current_request->clear() ;
// Wrong number of fields
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read timestamp.\n" ;
return *current_request ;
return false ;
}
current_request->set_time_sent(timestamp) ;
@ -84,11 +76,10 @@ const Request& InputCSV::get_next_request()
Point3D position ;
if (! file.read_point3d(position))
{
// Wrong number of fields: blank current request
current_request->clear() ;
// Wrong number of fields
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read coordinates.\n" ;
return *current_request ;
return false ;
}
// Read direction field
@ -96,11 +87,10 @@ const Request& InputCSV::get_next_request()
int direction_int ;
if (! file.read_field(direction_int))
{
// Wrong number of fields: blank current request
current_request->clear() ;
// Wrong number of fields
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read direction.\n" ;
return *current_request ;
return false ;
}
if (direction_int != 0)
direction = direction_int ;
@ -114,11 +104,10 @@ const Request& InputCSV::get_next_request()
int ss ;
if (! file.read_field(ss))
{
// Wrong number of fields: blank current request
current_request->clear() ;
// Wrong number of fields
if (Configuration::is_configured("verbose"))
cerr << "InputCSV: cannot read mac_ap.\n" ;
return *current_request ;
return false ;
}
PosUtil::to_upper(mac_ap) ;
@ -131,26 +120,11 @@ const Request& InputCSV::get_next_request()
measurements[mac_ap].add_ss(ss) ;
}
if (measurements.empty())
{
current_request->clear() ;
return *current_request ;
}
return false ;
current_request->set_measurements(measurements) ;
// Calibration request?
if (type == OWL_REQUEST_CALIBRATION ||
type == OWL_REQUEST_AUTOCALIBRATION)
{
const ReferencePoint &reference_point =
Stock::find_create_reference_point(position) ;
current_request_to_calibration_request(&reference_point,
direction, type) ;
}
fill_calibration_request_data(mac_mobile, position, direction, type) ;
// We set the real coordinates (if found) only for non-calibration
// requests
else if (position)
current_request->set_real_position(position) ;
return *current_request ;
return true ;
}

View File

@ -16,6 +16,12 @@ class InputCSV: public InputMedium
protected:
CSVFileReader file ;
/** @name Operations */
//@{
/// Reads data & fills the current request
bool fill_current_request(void) ;
//@}
public:
InputCSV(const std::string &filename):
file(filename) {}
@ -28,12 +34,6 @@ public:
bool eof(void) const ;
//@}
/** @name Operations */
//@{
/// Reads the next request
const Request& get_next_request(void) ;
//@}
/** @name Operators */
//@{
operator bool(void) const ;

View File

@ -1,5 +1,10 @@
#include "inputmedium.hh"
#include "calibrationrequest.hh"
#include "stock.hh"
#include "configuration.hh"
#include "posexcept.hh"
using namespace std ;
@ -23,6 +28,116 @@ InputMedium::~InputMedium()
/* *** Operations *** */
/**
* Reads a Request, increments current_line_nb, updates #current_request
* and returns it.
*
* The input medium should be ready to be read before precessing
* requests; otherwise, #current_request is \link Request::clear()
* cleared\endlink and a blank Request is returned.
*
* @return The Request read, or an empty Request in case of error or
* EOF (note that when casted in bool, an empty Request is \em false,
* see Request::operator bool()).
*/
const Request& InputMedium::get_next_request()
{
clear_current_request() ;
if (! fill_current_request())
{
clear_current_request() ;
return *current_request ;
}
return *current_request ;
}
void InputMedium::clear_current_request()
{
if (dynamic_cast<CalibrationRequest*>(current_request) == NULL)
current_request->clear() ;
else
{
delete current_request ;
current_request = NULL ;
current_request = new Request() ;
}
}
/**
* The \em position argument can be changed by this function.
*/
void InputMedium::
fill_calibration_request_data(const string &mac_mobile, Point3D &position,
const Direction &direction, uint8_t type)
{
// We set the real coordinates (if found) for non-calibration requests
if (type != OWL_REQUEST_CALIBRATION &&
type != OWL_REQUEST_AUTOCALIBRATION)
{
if (position)
current_request->set_real_position(position) ;
return ;
}
if (position)
{
// Update the AP's coordinates if allowed (and if the mobile is
// an AP, of course)
if (Configuration::
bool_value("positioning.update-ap-coordinates-online"))
{
if (type == OWL_REQUEST_AUTOCALIBRATION &&
Configuration::bool_value("positioning.accept-new-aps"))
{
AccessPoint &transmitter =
const_cast<AccessPoint&>(
Stock::find_create_ap(mac_mobile)) ;
transmitter.set_coordinates(position) ;
}
else
{
try
{
AccessPoint &transmitter =
const_cast<AccessPoint&>(Stock::get_ap(mac_mobile)) ;
transmitter.set_coordinates(position) ;
}
catch (element_not_found &e)
{
// The mobile is not an AP or the AP does not exist
}
}
}
}
else if (type == OWL_REQUEST_AUTOCALIBRATION)
{
// If an autocalibration request does not contain the coordinates
// of the AP, we use the current coordinates of the AP as
// ReferencePoint.
try
{
AccessPoint &transmitter =
const_cast<AccessPoint&>(Stock::get_ap(mac_mobile)) ;
position = transmitter.get_coordinates() ;
}
catch (element_not_found &e)
{
// The mobile is not an AP or the AP does not exist
}
}
const ReferencePoint &reference_point =
Stock::find_create_reference_point(position) ;
current_request_to_calibration_request(
&reference_point, direction, type) ;
}
void InputMedium::
current_request_to_calibration_request(
const ReferencePoint *const reference_point,
@ -47,16 +162,3 @@ current_request_to_calibration_request(
direction, request_type) ;
delete tmp ;
}
void InputMedium::clear_current_request()
{
if (dynamic_cast<CalibrationRequest*>(current_request) == NULL)
current_request->clear() ;
else
{
delete current_request ;
current_request = NULL ;
current_request = new Request() ;
}
}

View File

@ -6,6 +6,8 @@ class Direction ;
#include "request.hh"
#include <string>
/// Super class of all input media
/**
* This class Provides an interface for input media, i.e. to read
@ -18,6 +20,18 @@ protected:
/// Number of the current line proceeded
unsigned long current_line_nb ;
/** @name Operations */
//@{
/// Reads data & fills the current request
virtual bool fill_current_request(void) = 0 ;
/// \brief Checks if the current request is a calibration request and
/// if so fills it with additionnal data
void fill_calibration_request_data(const std::string &mac_mobile,
Point3D &position,
const Direction &direction,
uint8_t type) ;
//@}
public:
InputMedium(void) ;
@ -43,14 +57,7 @@ public:
//@{
/// Reads the next request
/**
* Reads a Request, increments current_line_nb, updates #current_request
* and returns it.
* @return The Request read, or an empty Request in case of error or
* EOF (note that when casted in bool, an empty Request is \em false,
* see Request::operator bool()).
*/
virtual const Request& get_next_request(void) = 0 ;
const Request& get_next_request(void) ;
/// Converts #current_request into a CalibrationRequest
void current_request_to_calibration_request(

View File

@ -72,22 +72,16 @@ bool InputUDPSocket::close_socket()
/**
* This function reads the next Request in the UDP input socket.
* It cannot read calibration requests.
* This function fills the current Request from the UDP input socket.
*
* #sockfd should be opened before processing requests; otherwise,
* #current_request is \link Request::clear() cleared\endlink and a
* blank Request is returned.
*
* @return The read Request, or a blank Request in case of error (socket
* not opened, bad packet format).
* @returns \em true if #current_request was correctly filled.
* @returns \em false in case of error (socket not opened, bad packet
* format).
*/
const Request& InputUDPSocket::get_next_request()
bool InputUDPSocket::fill_current_request()
{
clear_current_request() ;
if (eof())
return *current_request ;
return false ;
struct sockaddr_in client; // UDP client structure
socklen_t client_len = sizeof(client) ; // Size of clients
@ -98,8 +92,8 @@ const Request& InputUDPSocket::get_next_request()
(struct sockaddr *) &client, &client_len) ;
if (nread <= 0)
{
cerr << "No request received!" << endl ;
return *current_request ;
cerr << "InputUDPSocket: No request received!" << endl ;
return false ;
}
// Endianess conversions
@ -113,7 +107,7 @@ const Request& InputUDPSocket::get_next_request()
if (! Configuration::bool_value("positioning.accept-new-mobiles") &&
! Stock::mobile_exists(mac_mobile))
return *current_request ;
return false ;
const Mobile &mobile = Stock::find_create_mobile(mac_mobile) ;
current_request->set_mobile(&mobile) ;
@ -139,8 +133,7 @@ const Request& InputUDPSocket::get_next_request()
if (nread <= 0)
{
cerr << "No request info received!" << endl ;
current_request->clear() ;
return *current_request ;
return false ;
}
string mac_ap(
owl_mac_bytes_to_string(request_info.ap_mac_addr_bytes)) ;
@ -156,47 +149,12 @@ const Request& InputUDPSocket::get_next_request()
(request_info.antenna_signal_dbm)) ;
}
if (measurements.empty())
{
current_request->clear() ;
return *current_request ;
}
return false ;
current_request->set_measurements(measurements) ;
// Calibration request?
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)) ;
fill_calibration_request_data(
mac_mobile, position, request.direction, request.type) ;
// 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,
Direction(request.direction),
request.type) ;
}
// We set the real coordinates (if found) only for non-calibration
// requests
else if (position)
current_request->set_real_position(position) ;
return *current_request ;
return true ;
}

View File

@ -14,6 +14,15 @@ protected:
//@{
/// Initialises the socket
bool init_socket(void) ;
/// Reads data & fills the current request
/**
* This function fills the current Request from the data read from
* the input medium.
*
* @returns \em true if #current_request was correctly filled.
* @returns \em false in case of error.
*/
bool fill_current_request(void) ;
//@}
public:
@ -29,8 +38,6 @@ public:
/** @name Operations */
//@{
/// Reads the next request
const Request& get_next_request(void) ;
/// Closes the socket
bool close_socket(void) ;
//@}

View File

@ -124,7 +124,7 @@ void Measurement::update_average_ss()
/* *** Operators *** */
const Measurement& Measurement::operator=(const Measurement &m)
Measurement& Measurement::operator=(const Measurement &m)
{
if (this == &m)
return *this ;

View File

@ -68,7 +68,7 @@ public:
/** @name Operators */
//@{
const Measurement& operator=(const Measurement &m) ;
Measurement& operator=(const Measurement &m) ;
bool operator==(const Measurement &m) const ;
bool operator!=(const Measurement &m) const ;
operator bool(void) const ;

View File

@ -5,7 +5,7 @@
/* *** Operators *** */
const Mobile& Mobile::operator=(const Mobile &m)
Mobile& Mobile::operator=(const Mobile &m)
{
if (this == &m)
return *this ;

View File

@ -28,7 +28,7 @@ public:
/** @name Operators */
//@{
const Mobile& operator=(const Mobile &m) ;
Mobile& operator=(const Mobile &m) ;
bool operator==(const Mobile &m) const ;
bool operator!=(const Mobile &m) const ;
//@}

View File

@ -18,16 +18,16 @@ MultilaterationAlgorithm::MultilaterationAlgorithm():
// Will be changed when other multilateration methods will be
// implemented.
if (! Configuration::is_configured("positioning.minmax-start") ||
! Configuration::is_configured("positioning.minmax-stop"))
if (! Configuration::is_configured("positioning.area-start") ||
! Configuration::is_configured("positioning.area-stop"))
throw missing_configuration(
"You want to use MinMax, but either positioning.minmax-start or"
" positioning.minmax-stop is not defined!") ;
"You want to use MinMax, but either positioning.area-start or"
" positioning.area-stop is not defined!") ;
Point3D minmax_start(
Configuration::string_value("positioning.minmax-start")) ;
Configuration::string_value("positioning.area-start")) ;
Point3D minmax_stop(
Configuration::string_value("positioning.minmax-stop")) ;
Configuration::string_value("positioning.area-stop")) ;
multilateration_method = new MinMax(minmax_start, minmax_stop) ;
}
@ -47,19 +47,15 @@ double MultilaterationAlgorithm::
make_constant_term(const Measurement &measurement)
{
assert(request) ;
assert(request->get_mobile()) ;
const Mobile *mobile = request->get_mobile() ;
assert(mobile) ;
const AccessPoint *ap = measurement.get_ap() ;
assert(ap) ;
return
ap->get_trx_power() +
ap->get_antenna_gain() +
20 * log10(
static_cast<double>(PosUtil::LIGHT_SPEED) /
ap->get_frequency() /
(4 * M_PI)
) +
request->get_mobile()->get_antenna_gain() ;
ap->friis_constant_term() +
mobile->get_antenna_gain() +
mobile->get_trx_power() ;
}

View File

@ -6,8 +6,7 @@
/// Writes results to a CSV file
/**
* CSV format is:
* Mobile_MAC;Timestamp;Algorithm1;X;Y;Z;;AlgorithmN;X;Y;Z
* The CSV format is documented in ResultList::to_csv().
*/
class OutputCSV: public OutputMedium
{

View File

@ -0,0 +1,60 @@
#include "outputnetworksocket.hh"
#include "resultlist.hh"
#include "result.hh"
#include "posexcept.hh"
#include <cstdio> // For perror()
using namespace std ;
/* *** Constructors *** */
OutputNetworkSocket::~OutputNetworkSocket()
{
close_socket() ;
}
/* *** Operations *** */
/**
* 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 OutputNetworkSocket::close_socket()
{
if (sockfd >= 0)
{
if (close(sockfd))
{
perror("Cannot close network socket") ;
return false ;
}
sockfd = -1 ;
}
return true ;
}
void OutputNetworkSocket::write(const Result &result)
{
send_data(result.to_csv()) ;
}
void OutputNetworkSocket::write(const ResultList &results)
{
if (! results.empty())
send_data(results.to_csv()) ;
}

View File

@ -0,0 +1,50 @@
#ifndef _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_
#define _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_
#include "outputmedium.hh"
#include <string>
#include <stdint.h> // <cstdint> is not C++ 98 compliant
#include <arpa/inet.h>
/// Parent class for all output media that use network sockets
class OutputNetworkSocket: 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
/**
* You are required to call this function from the constructor of any
* derived class.
*/
virtual bool init_socket(void) = 0 ;
/// Sends a string through the socket
virtual bool send_data(const std::string &data) const = 0 ;
//@}
public:
OutputNetworkSocket(const std::string &_remote_host,
const uint_fast16_t _remote_port):
sockfd(-1), remote_host(_remote_host), remote_port(_remote_port) {}
~OutputNetworkSocket(void) ;
/** @name Operations */
//@{
/// Sends a list of results through the socket
void write(const ResultList &results) ;
/// Sends a single result through the socket
void write(const Result &result) ;
/// Closes the socket
bool close_socket(void) ;
//@}
} ;
#endif // _OWLPS_POSITIONING_OUTPUTNETWORKSOCKET_HH_

View File

@ -17,19 +17,13 @@ using namespace std ;
/* *** Constructors *** */
OutputTCPSocketEvAAL::OutputTCPSocketEvAAL(
const string &_remote_host,
const uint_fast16_t _remote_port):
remote_host(_remote_host), remote_port(_remote_port)
OutputTCPSocketEvAAL::
OutputTCPSocketEvAAL(const string &_remote_host,
const uint_fast16_t _remote_port):
OutputNetworkSocket(_remote_host, _remote_port)
{
if (! init_socket())
throw error_opening_output_file("TCP socket") ;
}
OutputTCPSocketEvAAL::~OutputTCPSocketEvAAL()
{
close_socket() ;
throw error_opening_output_file("TCP socket (EvAAL)") ;
}
@ -70,31 +64,6 @@ bool OutputTCPSocketEvAAL::init_socket()
}
/**
* 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.
@ -128,7 +97,7 @@ void OutputTCPSocketEvAAL::write(const Result &result)
int OutputTCPSocketEvAAL::
area_of_interest_number(const Point3D &position) const
{
const Area *area = Stock::in_which_area_is(position) ;
const Area *const area = Stock::in_which_area_is(position) ;
if (area == NULL)
return 0 ;
@ -157,7 +126,7 @@ 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") ;
perror("Error sending result data through the TCPEvAAL socket") ;
return false ;
}
return true ;

View File

@ -3,27 +3,16 @@
class Point3D ;
#include "outputmedium.hh"
#include <string>
#include <stdint.h> // <cstdint> is not C++ 98 compliant
#include <arpa/inet.h>
#include "outputnetworksocket.hh"
/// 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
class OutputTCPSocketEvAAL: public OutputNetworkSocket
{
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
@ -37,16 +26,15 @@ protected:
public:
OutputTCPSocketEvAAL(const std::string &_remote_host,
const uint_fast16_t _remote_port) ;
~OutputTCPSocketEvAAL(void) ;
/** @name Operations */
//@{
/// Sends a list of results through the socket
void write(const ResultList &results) ;
/// Sends a single result through the socket
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) ;
//@}
} ;

View File

@ -1,11 +1,11 @@
#include "outputudpsocket.hh"
#include "request.hh"
#include "resultlist.hh"
#include "result.hh"
#include "posexcept.hh"
#include <owlps.h>
#include <sstream>
#include <cstdio> // For perror()
using namespace std ;
@ -17,17 +17,10 @@ using namespace std ;
OutputUDPSocket::OutputUDPSocket(const string &_remote_host,
const uint_fast16_t _remote_port):
remote_host(_remote_host), remote_port(_remote_port)
OutputNetworkSocket(_remote_host, _remote_port)
{
if (! init_socket())
throw error_opening_output_file("UDP socket") ;
}
OutputUDPSocket::~OutputUDPSocket()
{
close_socket() ;
}
@ -47,52 +40,18 @@ bool OutputUDPSocket::init_socket()
}
/**
* 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 OutputUDPSocket::close_socket()
{
if (sockfd >= 0)
{
if (close(sockfd))
{
perror("Cannot close UDP socket") ;
return false ;
}
sockfd = -1 ;
}
return true ;
}
void OutputUDPSocket::write(const Result &result)
{
send_data(result.to_csv()) ;
}
void OutputUDPSocket::write(const ResultList &results)
{
if (! results.empty())
send_data(results.to_csv()) ;
}
/**
* Sends the text buffer 'data'.
*/
void OutputUDPSocket::send_data(const string &data)
bool OutputUDPSocket::send_data(const string &data) const
{
ssize_t nsent = sendto(sockfd, data.c_str(), data.size(), 0,
(struct sockaddr *) &server_info,
sizeof(server_info)) ;
if (nsent != static_cast<ssize_t>(data.size()))
perror("Error sending result data") ;
{
perror("Error sending result data through the UDP socket") ;
return false ;
}
return true ;
}

View File

@ -1,46 +1,28 @@
#ifndef _OWLPS_POSITIONING_OUTPUTUDPSOCKET_HH_
#define _OWLPS_POSITIONING_OUTPUTUDPSOCKET_HH_
#include "outputmedium.hh"
#include <string>
#include <stdint.h> // <cstdint> is not C++ 98 compliant
#include <arpa/inet.h>
#include "outputnetworksocket.hh"
/// Sends results to a remote host by UDP
/**
* The results are sent through an UDP socket as a CSV string value. The
* format used is the same as in OutputCSV.
* The results are sent through an UDP socket as a CSV string value.
* The format used is the same as in OutputCSV, and is documented in
* ResultList::to_csv().
*/
class OutputUDPSocket: public OutputMedium
class OutputUDPSocket: public OutputNetworkSocket
{
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) ;
void send_data(const std::string &data) ;
/// Sends a string through the socket
bool send_data(const std::string &data) const ;
//@}
public:
OutputUDPSocket(const std::string &_remote_ip,
const uint_fast16_t _port) ;
~OutputUDPSocket(void) ;
/** @name Operations */
//@{
void write(const Result &result) ;
void write(const ResultList &results) ;
/// Closes the socket
bool close_socket(void) ;
//@}
OutputUDPSocket(const std::string &_remote_host,
const uint_fast16_t _remote_port) ;
} ;

View File

@ -93,7 +93,7 @@ double Point3D::angle(const Point3D &b, const Point3D &c) const
/* *** Operators *** */
const Point3D& Point3D::operator=(const Point3D &source)
Point3D& Point3D::operator=(const Point3D &source)
{
if (this == &source)
return *this ;

View File

@ -67,7 +67,7 @@ public:
/** @name Operators */
//@{
const Point3D& operator=(const Point3D &source) ;
Point3D& operator=(const Point3D &source) ;
bool operator==(const Point3D &source) const ;
bool operator!=(const Point3D &source) const ;
bool operator<(const Point3D &source) const ;

View File

@ -61,7 +61,12 @@ void Positioning::initialise_algorithms()
else if (*i == "FBCM")
{
Stock::update_all_friis_indexes() ;
// Generate the Friis indexes only if the autocalibration is
// not activated (if it is, Friis indexes will be regenerated
// each time FBCM wants to computes a position)
if (! Configuration::
bool_value("positioning.generate-reference-points"))
Stock::update_all_friis_indexes() ;
algorithms.push_back(new FBCM) ;
}

View File

@ -204,13 +204,7 @@ float ReferencePoint::
friis_index_for_ap(const string &ap_mac) const
{
const AccessPoint &ap = Stock::get_ap(ap_mac) ;
double ap_freq = ap.get_frequency() ;
double const_term =
ap.get_antenna_gain()
- 20 * log10(4 * M_PI)
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
+ ap.get_trx_power() ;
double const_term = ap.friis_constant_term() ;
int nb_friis_idx = 0 ;
double friis_idx_sum =
@ -258,8 +252,10 @@ float ReferencePoint::friis_indexes_for_ap(
assert((*request)->get_mobile()) ;
float mobile_gain =
(*request)->get_mobile()->get_antenna_gain() ;
float mobile_pow =
(*request)->get_mobile()->get_trx_power() ;
friis_idx_sum +=
(const_term + mobile_gain - ss)
(const_term + mobile_gain + mobile_pow - ss)
/ (10 * log10(distance)) ;
++nb_indexes ;
}
@ -272,8 +268,7 @@ float ReferencePoint::friis_indexes_for_ap(
/* *** Operators *** */
const ReferencePoint& ReferencePoint::
operator=(const ReferencePoint &source)
ReferencePoint& ReferencePoint::operator=(const ReferencePoint &source)
{
if (this == &source)
return *this ;

View File

@ -75,7 +75,7 @@ public:
/** @name Operators */
//@{
const ReferencePoint& operator=(const ReferencePoint &source) ;
ReferencePoint& operator=(const ReferencePoint &source) ;
bool operator==(const ReferencePoint &source) const ;
bool operator!=(const ReferencePoint &source) const ;
//@}

View File

@ -79,7 +79,7 @@ float Request::ss_square_distance(const Request &source) const
/* *** Operators *** */
const Request& Request::operator=(const Request &source)
Request& Request::operator=(const Request &source)
{
if (this == &source)
return *this ;

View File

@ -94,7 +94,7 @@ public:
/** @name Operators */
//@{
const Request& operator=(const Request &source) ;
Request& operator=(const Request &source) ;
bool operator==(const Request &comp) const ;
bool operator!=(const Request &comp) const ;
operator bool(void) const ;

View File

@ -50,7 +50,7 @@ void Result::compute_error(const Point3D &real_position)
/* *** Operators *** */
const Result& Result::operator=(const Result &source)
Result& Result::operator=(const Result &source)
{
if (this == &source)
return *this ;
@ -76,7 +76,12 @@ bool Result::operator==(const Result &source) const
/**
* @return The result as a CSV string, \em without trailing '\n'.
* This function creates a CSV string from the Result's data.
*
* The format used is the following:
* Algorithm_name;X;Y;Z;Error;Area_name
*
* @return The result as a CSV string, \em without a trailing '\\n'.
*/
const string Result::to_csv() const
{
@ -87,8 +92,12 @@ const string Result::to_csv() const
<< ';' << position.get_x()
<< ';' << position.get_y()
<< ';' << position.get_z()
<< ';' << "Error"
<< ';' << error ;
<< ';' << error
<< ';' ;
const Area *const area = Stock::in_which_area_is(position) ;
if (area != NULL)
csv_line << area->get_name() ;
return csv_line.str() ;
}

View File

@ -49,7 +49,7 @@ public:
/** @name Operators */
//@{
const Result& operator=(const Result &source) ;
Result& operator=(const Result &source) ;
bool operator==(const Result &source) const ;
bool operator!=(const Result &source) const ;
//@}

View File

@ -21,7 +21,7 @@ ResultList::~ResultList()
/* *** Operators *** */
const ResultList& ResultList::operator=(const ResultList &source)
ResultList& ResultList::operator=(const ResultList &source)
{
if (this == &source)
return *this ;
@ -46,7 +46,15 @@ bool ResultList::operator==(const ResultList &source) const
/**
* @return The results as a CSV string, \em without trailing '\n'.
* This function creates a CSV string from the Result's data.
*
* The format used is the following:
* Mobile_MAC;Request_type;Timestamp;[Algorithm_1];;[Algorithm_n]
*
* The CSV format for the [Algorithm_i] strings is documented in
* Result::to_csv().
*
* @return The results as a CSV string, \em without a trailing '\\n'.
*/
const string ResultList::to_csv() const
{

View File

@ -38,7 +38,7 @@ public:
/** @name Operators */
//@{
const ResultList& operator=(const ResultList &source) ;
ResultList& operator=(const ResultList &source) ;
bool operator==(const ResultList &source) const ;
bool operator!=(const ResultList &source) const ;
//@}

View File

@ -87,7 +87,7 @@ 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)
const Area* Stock::in_which_area_is(const Point3D &point)
{
for (unordered_map<string, Building>::const_iterator
b = buildings.begin() ; b != buildings.end() ; ++b)
@ -281,12 +281,7 @@ void Stock::update_all_friis_indexes()
int nb_friis_idx = 0 ;
// Compute main general term, independant from scans
double ap_freq = ap->second.get_frequency() ;
double const_term =
ap->second.get_antenna_gain()
- 20 * log10(4 * M_PI)
+ 20 * log10(PosUtil::LIGHT_SPEED / ap_freq)
+ ap->second.get_trx_power() ;
double const_term = ap->second.friis_constant_term() ;
/*
* Compute indexes for each ReferencePoint. The Friis index for an
@ -424,48 +419,12 @@ 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 ;
}
delete_non_ap_calibration_requests() ;
if (reference_points.size() < 3)
{
@ -477,15 +436,15 @@ void Stock::regenerate_reference_points()
}
/* Generate RPs */
if (! Configuration::is_configured("positioning.minmax-start") ||
! Configuration::is_configured("positioning.minmax-stop"))
if (! Configuration::is_configured("positioning.area-start") ||
! Configuration::is_configured("positioning.area-stop"))
throw missing_configuration(
"You must define the deployment area in order to generate"
" reference points.") ;
Point3D start(
Configuration::string_value("positioning.minmax-start")) ;
Configuration::string_value("positioning.area-start")) ;
Point3D stop(
Configuration::string_value("positioning.minmax-stop")) ;
Configuration::string_value("positioning.area-stop")) ;
float step_x =
Configuration::float_value("positioning.generated-meshing-grain-x") ;
float step_y =
@ -496,150 +455,161 @@ void Stock::regenerate_reference_points()
//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 &current_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(&current_rp) ;
store_calibration_request(cr) ;
generate_reference_point(current_point) ;
}
}
/**
* The reference point P we want to generate will end-up containing
* as many calibration requests as the total number of APs.
* For each of these requests, we consider a transmitter TRX (which is
* a virtual mobile) 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::generate_reference_point(const Point3D &point)
{
// If the point is the coordinates of an existing AP, we don't
// need to generate it
if (is_ap_coordinate(point))
return ;
/* Get/create the reference point */
const ReferencePoint &current_rp =
find_create_reference_point(point) ;
/* Create the timestamp */
Timestamp time_sent ;
time_sent.now() ;
/* Create the measurement list */
unordered_map<string, Measurement> measurements ;
/* Prepare the virtual mobile */
string vmob_mac(PosUtil::int_to_mac(nb_virtual_mobiles++)) ;
// The gain and trx power of the mobile will be the average of
// those of all the known APs (could be better, probably)
double vmob_gain = 0 ;
double vmob_pow = 0 ;
for (unordered_map<string, AccessPoint>::const_iterator
rx = aps.begin() ; rx != aps.end() ; ++rx)
{
/* Update the mobile's attributes */
vmob_gain += rx->second.get_antenna_gain() / aps.size() ;
vmob_pow += rx->second.get_trx_power() / aps.size() ;
/* 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(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 point_dst =
rx_coord.distance(point) ;
// Constant term
double common_ss = rx->second.friis_constant_term() ;
// 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(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(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(&current_rp) ;
store_calibration_request(cr) ;
}
/* *** CalibrationRequest operations *** */
@ -729,3 +699,32 @@ closest_calibration_request(const Request &request)
return *closest ;
}
void Stock::delete_non_ap_calibration_requests()
{
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 ;
}
}

View File

@ -41,6 +41,18 @@ private:
/// List of known CalibrationRequest
static std::tr1::unordered_set<CalibrationRequest> calibration_requests ;
/** @name ReferencePoint operations */
//@{
/// Generates a single reference point
static void generate_reference_point(const Point3D &point) ;
//@}
/** @name CalibrationRequest operations */
//@{
/// Delete calibration requests that do not come from the APs
static void delete_non_ap_calibration_requests(void) ;
//@}
public:
/** @name Building operations */
//@{
@ -51,7 +63,7 @@ public:
/// 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) ;
static const Area* in_which_area_is(const Point3D &point) ;
//@}
/** @name Waypoint operations */

View File

@ -144,7 +144,7 @@ bool Timestamp::greater_than(const struct timespec &source) const
/* *** Operators *** */
const Timestamp& Timestamp::operator=(const Timestamp &source)
Timestamp& Timestamp::operator=(const Timestamp &source)
{
if (this == &source)
return *this ;

View File

@ -62,9 +62,9 @@ public:
/** @name Operators */
//@{
const Timestamp& operator=(const Timestamp &source) ;
const Timestamp& operator=(const struct timespec &source) ;
const Timestamp& operator=(const uint64_t source) ; //< deprecated
Timestamp& operator=(const Timestamp &source) ;
Timestamp& operator=(const struct timespec &source) ;
Timestamp& operator=(const uint64_t source) ; //< deprecated
bool operator==(const Timestamp &source) const ;
bool operator==(const struct timespec &source) const ;
bool operator==(const uint64_t source) const ; //< deprecated
@ -109,15 +109,14 @@ inline void Timestamp::clear(void)
/* *** Operators *** */
inline const Timestamp& Timestamp::
operator=(const struct timespec &source)
inline Timestamp& Timestamp::operator=(const struct timespec &source)
{
set(source) ;
return *this ;
}
inline const Timestamp& Timestamp::operator=(const uint64_t source)
inline Timestamp& Timestamp::operator=(const uint64_t source)
{
set(source) ;
return *this ;

View File

@ -15,7 +15,7 @@ namespace po = boost::program_options ;
/* *** Default value definitions *** */
#define DEFAULT_CONFIG_FILE_NAME \
"/usr/local/etc/owlps/owlps-positioning.cfg"
"/usr/local/etc/owlps/owlps-positioning.conf"
#define DEFAULT_TCPEVAAL_HOST "127.0.0.1"
#define DEFAULT_TCPEVAAL_PORT 4444
@ -183,12 +183,15 @@ void UserInterface::fill_positioning_options()
"Algorithms used to compute positions. You can specify"
"this option more than once (but at least once). Allowed: Real, FBCM,"
" FRBHMBasic, InterlinkNetworks, RADAR.")
("positioning.minmax-start", po::value<string>(),
"Coordinates of the start point of the MinMax multilateration"
" method (string format: \"X;Y;Z\").")
("positioning.minmax-stop", po::value<string>(),
"Coordinates of the stop point of the MinMax multilateration"
" method (string format: \"X;Y;Z\").")
("positioning.area-start", po::value<string>(),
"Coordinates of the first point of the deployment area; this is"
" used to delimit the area in which the MinMax multilateration"
" method tests points and in which the reference points are"
" generated, if the corresponding options are activated"
" (string format: \"X;Y;Z\").")
("positioning.area-stop", po::value<string>(),
"Coordinates of the last point of the deployment area"
" (string format: \"X;Y;Z\").")
("positioning.radar-average-reference-points",
po::value<bool>()->default_value(false),
"With the RADAR algorithm, for a given positioning request, average"

View File

@ -53,7 +53,7 @@ Waypoint::~Waypoint()
/* *** Operators *** */
const Waypoint& Waypoint::operator=(const Waypoint &wp)
Waypoint& Waypoint::operator=(const Waypoint &wp)
{
if (this == &wp)
return *this ;

View File

@ -53,7 +53,7 @@ public:
/** @name Operators */
//@{
const Waypoint& operator=(const Waypoint &wp) ;
Waypoint& operator=(const Waypoint &wp) ;
bool operator==(const Waypoint &wp) const ;
bool operator!=(const Waypoint &wp) const ;
operator std::string(void) const ;

View File

@ -7,7 +7,7 @@ using namespace std ;
/* *** Operators *** */
const WifiDevice& WifiDevice::operator=(const WifiDevice &wd)
WifiDevice& WifiDevice::operator=(const WifiDevice &wd)
{
if (this == &wd)
return *this ;

View File

@ -52,7 +52,7 @@ public:
/** @name Operators */
//@{
const WifiDevice& operator=(const WifiDevice &wd) ;
WifiDevice& operator=(const WifiDevice &wd) ;
bool operator==(const WifiDevice &wd) const ;
bool operator!=(const WifiDevice &wl) const ;
//@}