Skip to content

Commit

Permalink
Merge pull request #57 from marcomicera/fix_statistics (#55)
Browse files Browse the repository at this point in the history
Various statistics' fixes
  • Loading branch information
marcomicera authored Nov 21, 2019
2 parents 5a7478f + 0727a10 commit f7f8c27
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 68 deletions.
5 changes: 3 additions & 2 deletions board/followifier/main/components/sniffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ void hexDump(char *desc, void *addr, int len) {
}

// And print the final ASCII bit.
printf(" %s\n\n", buff);
printf(" %s\n", buff);
}

/**
Expand Down Expand Up @@ -238,7 +238,8 @@ void sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type) {
now,
ppkt->rx_ctrl.rssi
);
hexDump(NULL, ppkt->payload, ppkt->rx_ctrl.sig_len);
// hexDump(NULL, ppkt->payload, ppkt->rx_ctrl.sig_len);
printf("\n");
Followifier__ESP32Message message = FOLLOWIFIER__ESP32_MESSAGE__INIT;
Followifier__ESP32Metadata metadata = FOLLOWIFIER__ESP32_METADATA__INIT;

Expand Down
2 changes: 1 addition & 1 deletion common/message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ syntax = "proto2";
package followifier;

message ESP32Metadata {
required string apMac = 1;
required string apMac = 1; // FIXME change it into `deviceMac`
required string ssid = 2;
required int64 timestamp = 3;
required int32 rsi = 5;
Expand Down
14 changes: 10 additions & 4 deletions core/examples/dummy_packets/dummy_packet_producer.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,17 @@ def gen_dummy_batch_base(batch_size):
return batch


def gen_dummy_batch(batch, mac, common_hashes):
def gen_dummy_batch(batch, mac, common_hashes, a):
used_common_hashes = 0
batch.boardMac = mac
for message in batch.messages:

# Setting a random RSSI
message.metadata.rsi = -24
if a:
message.metadata.rsi = -62;
else:
message.metadata.rsi = -51;


# Introduce a common frame hash as long as there are some available
if len(common_hashes) > used_common_hashes:
Expand All @@ -74,7 +78,7 @@ def fill_message(message):
message.metadata.ssid = gen_random_ssid()
message.metadata.timestamp = gen_random_timestamp()
# message.frame_hash = gen_random_hash()
message.metadata.rsi = -24;


def main():
Expand Down Expand Up @@ -104,15 +108,17 @@ def main():
print("\nNew round, " + str(num_common_hashes) + " messages will be stored in the database.")

# Simulating multiple boards
check = True
for board_mac_address in args.boards_mac:
try:
batch = gen_dummy_batch(batch_base, board_mac_address, common_hashes).SerializeToString()
batch = gen_dummy_batch(batch_base, board_mac_address, common_hashes, check).SerializeToString()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((args.ip, args.port))
s.send(batch)
s.send(b'\n\r\n\r')
print("Board " + board_mac_address + " has sent a batch.")
s.close()
check = not check
except ConnectionRefusedError:
print("Server not available.")

Expand Down
7 changes: 6 additions & 1 deletion core/server/src/point.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "point.h"
#include <stdexcept>
#include <cmath>

double Point::getX() {
return this->x;
}
Expand Down Expand Up @@ -28,4 +29,8 @@ bool Point::isValid() {
if(!std::isnan(x) && !std::isnan(y))
return true;
return false;
}
}

std::ostream& operator<<(std::ostream &ostream, const Point &point) {
return ostream << "< x = " << point.x << ", y = " << point.y << ">";
}
5 changes: 4 additions & 1 deletion core/server/src/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
#define CORE_POINT_H

#include <cstdint>
#include <ostream>

class Point {

public:

Point(double x, double y);

// id is returned as hash function
// id is returned as hash function
bool operator==(const Point &other) const;

struct PointHasher {
Expand All @@ -23,6 +24,8 @@ class Point {
double getY();
bool isValid();

friend std::ostream& operator<<(std::ostream&, const Point&);

private:

double x;
Expand Down
16 changes: 9 additions & 7 deletions core/server/src/receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,21 @@ void receiver::addBatch(const followifier::Batch &newBatch, database &database)
if (messagesBuffer.find(newMessage.frame_hash())->second.size() == NUMBER_BOARDS) {

aFrameHasBeenSentByAllBoards = true;
cout << "Message " << prettyHash(newMessage.frame_hash()) << " has been sent by all boards." << endl;

Point position = statistics::getPosition(newMessage.frame_hash(),
messagesBuffer.find(newMessage.frame_hash())->second);
if (!position.isValid()){
/* Computing device position */
Point devicePosition = statistics::getDevicePosition(messagesBuffer.find(newMessage.frame_hash())->second);
cout << "Device location: " << devicePosition << endl;
if (!devicePosition.isValid()){
cerr << "Message " << prettyHash(newMessage.frame_hash()) << " discarded for invalid position" << endl;
return;
}
cout << endl;

/* Storing it into the database */
cout << "Message " << prettyHash(newMessage.frame_hash()) << " has been sent by all boards from position "
<< position.getX() << "," << position.getY() << endl;
/* Compute position */
// FIXME The following should store all these statistics
database.insert_message(newMessage, position); // TODO check object internal representation in MongoDB
// TODO check object internal representation in MongoDB
database.insert_message(newMessage, devicePosition);

/* Clearing the entry relative to this frame */
messagesBuffer.erase(newMessage.frame_hash());
Expand Down
12 changes: 7 additions & 5 deletions core/server/src/receiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,16 @@ class receiver {
* @param cause the cause that led the start of a new round.
*/
static void newRound(const std::string &cause) {
std::cout << cause << " " << std::flush; // TODO glog
std::cout << "Starting a new round..." << std::endl;
if (lastRoundBoardMacs.size() == NUMBER_BOARDS) {
std::cout << std::endl << std::endl;
}
if (!ROUNDLESS_MODE) {
std::cout << cause << " " << std::flush; // TODO glog
std::cout << "Starting a new round..." << std::endl;
if (lastRoundBoardMacs.size() == NUMBER_BOARDS) {
std::cout << std::endl << std::endl;
}
lastRoundBoardMacs.clear();
messagesBuffer.clear();
} else {
std::cout << std::endl << std::endl;
}
}

Expand Down
97 changes: 57 additions & 40 deletions core/server/src/statistics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,52 @@
#include "settings.h"
#include <iostream>

Point statistics::getPosition(std::string hash, std::unordered_map< std::string, followifier::ESP32Metadata> &messageBoardsAndMetadata) {
Point statistics::getDevicePosition(std::unordered_map<std::string, followifier::ESP32Metadata> &boardMetadatas) {

std::unordered_set<Point, Point::PointHasher> listPossiblePoints;
for (auto i = messageBoardsAndMetadata.begin(); i != messageBoardsAndMetadata.end(); i++) {
for (auto j = std::next(i, 1); j != messageBoardsAndMetadata.end(); j++) {
//calculate interception points
//d = sqrt((x1-x2)^2 + (y1-y2)^2)
double d = std::sqrt(
std::pow(Settings::configuration.boards.find(i->first)->second.getCoordinates().getX() -
Settings::configuration.boards.find(j->first)->second.getCoordinates().getX(), 2) +
std::pow(Settings::configuration.boards.find(i->first)->second.getCoordinates().getY() -
Settings::configuration.boards.find(j->first)->second.getCoordinates().getY(), 2));

//l = r1^2-r2^2 + d^2 / 2d
double l = (std::pow(statistics::estimatedDistance(i->second.rsi()), 2) - std::pow(statistics::estimatedDistance(j->second.rsi()), 2) + std::pow(d, 2)) / (2 * d);

//h = sqrt(r1^2 - l^2)
double h = std::sqrt(std::pow(statistics::estimatedDistance(i->second.rsi()), 2) - std::pow(l, 2));
//x = l(x2 - x1) / d + -h(y2 - y1) / d + x1
double x = (l * (Settings::configuration.boards.find(j->first)->second.getCoordinates().getX() -
Settings::configuration.boards.find(i->first)->second.getCoordinates().getX())) / d +
(h * (Settings::configuration.boards.find(j->first)->second.getCoordinates().getY() -
Settings::configuration.boards.find(i->first)->second.getCoordinates().getY())) / d +
Settings::configuration.boards.find(i->first)->second.getCoordinates().getX();
//y = h(y2 - y1) / d -+ l(x2 - x1) / d + y1
double y = (l * (Settings::configuration.boards.find(j->first)->second.getCoordinates().getY() -
Settings::configuration.boards.find(i->first)->second.getCoordinates().getY())) / d -
(h * (Settings::configuration.boards.find(j->first)->second.getCoordinates().getX() -
Settings::configuration.boards.find(i->first)->second.getCoordinates().getX())) / d +
Settings::configuration.boards.find(i->first)->second.getCoordinates().getY();

if (checkPoint(std::round(x), std::round(y), messageBoardsAndMetadata)) {
listPossiblePoints.insert(Point(std::round(x), std::round(y)));

for (auto i = boardMetadatas.begin(); i != boardMetadatas.end(); ++i) {
for (auto j = std::next(i, 1); j != boardMetadatas.end(); ++j) {

double x1 = Settings::configuration.boards.find(i->first)->second.getCoordinates().getX();
double x2 = Settings::configuration.boards.find(j->first)->second.getCoordinates().getX();
double y1 = Settings::configuration.boards.find(i->first)->second.getCoordinates().getY();
double y2 = Settings::configuration.boards.find(j->first)->second.getCoordinates().getY();

// Interception points
double r1 = statistics::estimatedDistance(i->second.rsi());
double r2 = statistics::estimatedDistance(j->second.rsi());
std::cout << "Board " << i->first << " announced device " << i->second.apmac() << " at a distance of " << r1
<< " cm." << std::endl;
std::cout << "Board " << j->first << " announced device " << j->second.apmac() << " at a distance of " << r2
<< " cm." << std::endl;

// d = sqrt((x1-x2)^2 + (y1-y2)^2)
double d = std::sqrt(std::pow(x1 - x2, 2) + std::pow(y1 - y2, 2));

// l = r1^2-r2^2 + d^2 / 2d
double l = (std::pow(r1, 2) - std::pow(r2, 2) + std::pow(d, 2)) / (2 * d);

// h = sqrt(r1^2 - l^2)
double h = std::sqrt(std::pow(r1, 2) - std::pow(l, 2));

/*
* Results
*/

// x results = l(x2 - x1) / d + -h(y2 - y1) / d + x1
double xr1 = l * (x2 - x1) / d + h * (y2 - y1) / d + x1;
double xr2 = l * (x2 - x1) / d - h * (y2 - y1) / d + x1;

// y results = l(y2 - y1) / d -+ h(x2 - x1) / d + y1
double yr1 = l * (y2 - y1) / d - h * (x2 - x1) / d + y1;
double yr2 = l * (y2 - y1) / d + h * (x2 - x1) / d + y1;

if (xr1 >= 0 && yr1 >= 0 && checkPoint(xr1, yr1, boardMetadatas) && Point(xr1, yr1).isValid()) {
listPossiblePoints.insert(Point(std::round(xr1), std::round(yr1)));
}
if (xr2 >= 0 && yr2 >= 0 && checkPoint(xr2, yr2, boardMetadatas) && Point(xr2, yr2).isValid()) {
listPossiblePoints.insert(Point(std::round(xr2), std::round(yr2)));
}
}
}
Expand All @@ -49,19 +63,22 @@ Point statistics::getPosition(std::string hash, std::unordered_map< std::string,
return center;
}

double statistics::estimatedDistance(double rssi){
double distance = std::pow(10, (ONE_METER_RSSI - rssi)/(10*2));
distance *= 1.1; // FIXME Make tolerance a variable
std::cout << "Estimated distance: " << distance << std::endl; // TODO glog
return distance * 100;
double statistics::estimatedDistance(double rssi) {
double distance = std::pow(10, (ONE_METER_RSSI - rssi) / (10 * 2)) * 100;
return distance * 1.1; // FIXME Make tolerance a variable
}

bool statistics::checkPoint(double x, double y,
std::unordered_map<std::string, followifier::ESP32Metadata> &boardsMedatada) {
for (auto & board : Settings::configuration.boards) {
if ((std::pow(x - board.second.getCoordinates().getX(), 2) + std::pow(y - board.second.getCoordinates().getY(), 2) -
std::pow(statistics::estimatedDistance(boardsMedatada.find(board.first)->second.rsi()), 2)) > 0)
std::unordered_map<std::string, followifier::ESP32Metadata> &boardMetadatas) {

for (auto &board : Settings::configuration.boards) {

if (std::sqrt(std::pow(x - board.second.getCoordinates().getX(), 2) +
std::pow(y - board.second.getCoordinates().getY(), 2)) -
std::pow(statistics::estimatedDistance(boardMetadatas.find(board.first)->second.rsi()), 2) > 0) {

return false;
}
}
return true;
}
4 changes: 2 additions & 2 deletions core/server/src/statistics.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
#include <unordered_map>
#include "../gen/message.pb.h"
#include "receiver.h"
#define ONE_METER_RSSI -67
#define ONE_METER_RSSI -65

class statistics {
public:
static Point getPosition(std::string, std::unordered_map <std::string, followifier::ESP32Metadata>&);
static Point getDevicePosition(std::unordered_map <std::string, followifier::ESP32Metadata> &boardMetadatas);

private:

Expand Down
6 changes: 1 addition & 5 deletions core/server/start.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#!/bin/bash

# Building the project
cmake .
make

# Allowing inbound and outbound TCP connections on the specified port
PORT=$(python3 -c "import json; print(json.load(open('./config.json'))['port'])")
echo Asking password to allow TCP inbound and outbound connections on port "$PORT" on this machine...
Expand All @@ -16,4 +12,4 @@ sudo apt-get install -y ntp
/etc/init.d/ntp start

# Launching the server
./core
cmake . && make && ./core

0 comments on commit f7f8c27

Please sign in to comment.