we are now able to record bluetooth fingerprints
for this, we use the same ui interface and fingerprint positions as wifi. if wifi has done 30 scans, also the ble scans will be stopped. this is just a quick and dirte solution, as changing the gui completely for this two options was to time consuming
This commit is contained in:
@@ -22,6 +22,9 @@
|
|||||||
#include <Indoor/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h>
|
#include <Indoor/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h>
|
||||||
#include <Indoor/sensors/radio/model/WiFiModel.h>
|
#include <Indoor/sensors/radio/model/WiFiModel.h>
|
||||||
|
|
||||||
|
#include <Indoor/sensors/beacon/model/BeaconModel.h>
|
||||||
|
#include <Indoor/sensors/beacon/model/BeaconModelLogDistCeiling.h>
|
||||||
|
|
||||||
#include <Indoor/Assertions.h>
|
#include <Indoor/Assertions.h>
|
||||||
|
|
||||||
#include "ui/LoggerUI.h"
|
#include "ui/LoggerUI.h"
|
||||||
@@ -244,6 +247,17 @@ WiFiModel* buildWiFiModelOnce(Floorplan::IndoorMap* map, const std::string& fpFi
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BeaconModel* buildBLEModelOnce(Floorplan::IndoorMap* map, const std::string& fpFile, const std::string& bleModelFile){
|
||||||
|
|
||||||
|
// ask questions
|
||||||
|
const QMessageBox::StandardButton replyWiFiFP = QMessageBox::question(nullptr, "BLE", "Use Fingerprints for Bluetooth Calibration?\n\nYes: Use fingerprints and num-optimize AP-Params\nNo: Use Beacons from the map.xml (pos+params)", QMessageBox::Yes|QMessageBox::No);
|
||||||
|
|
||||||
|
BeaconModel* bleModel = new BeaconModelLogDistCeiling(map);
|
||||||
|
|
||||||
|
return bleModel;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Controller::on3DButton() {
|
void Controller::on3DButton() {
|
||||||
|
|
||||||
static bool use3D = false;
|
static bool use3D = false;
|
||||||
@@ -272,6 +286,7 @@ void Controller::loadGrid(QDir dir) {
|
|||||||
QFile fMap(dir.path() + "/map.xml");
|
QFile fMap(dir.path() + "/map.xml");
|
||||||
QFile fGrid(dir.path() + "/grid.dat");
|
QFile fGrid(dir.path() + "/grid.dat");
|
||||||
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
|
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
|
||||||
|
QFile fBLEFP(dir.path() + "/ble_fp.dat");
|
||||||
|
|
||||||
Assert::isTrue(fMap.exists(), "map.xml missing");
|
Assert::isTrue(fMap.exists(), "map.xml missing");
|
||||||
//Assert::isTrue(fGrid.exists(), "grid.dat missing");
|
//Assert::isTrue(fGrid.exists(), "grid.dat missing");
|
||||||
@@ -285,6 +300,7 @@ void Controller::loadGrid(QDir dir) {
|
|||||||
//Assert::isTrue(inp.good(), "failed to open grid.dat");
|
//Assert::isTrue(inp.good(), "failed to open grid.dat");
|
||||||
|
|
||||||
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
|
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
|
||||||
|
const std::string sBLEFP = fBLEFP.fileName().toStdString();
|
||||||
|
|
||||||
// create a new, empty grid
|
// create a new, empty grid
|
||||||
if (grid) {delete grid; grid = nullptr;}
|
if (grid) {delete grid; grid = nullptr;}
|
||||||
@@ -302,9 +318,10 @@ void Controller::loadGrid(QDir dir) {
|
|||||||
nav = new GridBased::NavControllerGrid(this, im, grid);
|
nav = new GridBased::NavControllerGrid(this, im, grid);
|
||||||
|
|
||||||
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
|
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
|
||||||
|
BLECalibrationDataModel* bleCalib = new BLECalibrationDataModel(sBLEFP);
|
||||||
|
|
||||||
getMapView3D()->setMap(im);
|
getMapView3D()->setMap(im);
|
||||||
getMapView2D()->setMap(wifiCalib, im);
|
getMapView2D()->setMap(wifiCalib, bleCalib, im);
|
||||||
|
|
||||||
getMapView3D()->showGridImportance(grid);
|
getMapView3D()->showGridImportance(grid);
|
||||||
getMapView2D()->showGridImportance(grid);
|
getMapView2D()->showGridImportance(grid);
|
||||||
@@ -322,6 +339,7 @@ void Controller::loadNavMesh(QDir dir) {
|
|||||||
QFile fGrid(dir.path() + "/grid.dat");
|
QFile fGrid(dir.path() + "/grid.dat");
|
||||||
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
|
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
|
||||||
QFile fWiFiModel(dir.path() + "/wifimodel.dat");
|
QFile fWiFiModel(dir.path() + "/wifimodel.dat");
|
||||||
|
QFile fBLEFP(dir.path() + "/ble_fp.dat");
|
||||||
|
|
||||||
Assert::isTrue(fMap.exists(), "map.xml missing");
|
Assert::isTrue(fMap.exists(), "map.xml missing");
|
||||||
|
|
||||||
@@ -331,6 +349,7 @@ void Controller::loadNavMesh(QDir dir) {
|
|||||||
|
|
||||||
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
|
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
|
||||||
const std::string sWiFiModel = fWiFiModel.fileName().toStdString();
|
const std::string sWiFiModel = fWiFiModel.fileName().toStdString();
|
||||||
|
const std::string sBLEFP = fBLEFP.fileName().toStdString();
|
||||||
|
|
||||||
wifiModel = buildWiFiModelOnce(im, sWiFiFP, sWiFiModel);
|
wifiModel = buildWiFiModelOnce(im, sWiFiFP, sWiFiModel);
|
||||||
|
|
||||||
@@ -346,9 +365,10 @@ void Controller::loadNavMesh(QDir dir) {
|
|||||||
nav = new MeshBased::NavControllerMesh(this, im, navMesh, wifiModel);
|
nav = new MeshBased::NavControllerMesh(this, im, navMesh, wifiModel);
|
||||||
|
|
||||||
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
|
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
|
||||||
|
BLECalibrationDataModel* bleCalib = new BLECalibrationDataModel(sBLEFP);
|
||||||
|
|
||||||
getMapView3D()->setMap(im);
|
getMapView3D()->setMap(im);
|
||||||
getMapView2D()->setMap(wifiCalib, im);
|
getMapView2D()->setMap(wifiCalib, bleCalib, im);
|
||||||
|
|
||||||
//getMapView3D()->showGridImportance(grid);
|
//getMapView3D()->showGridImportance(grid);
|
||||||
//getMapView2D()->showGridImportance(grid);
|
//getMapView2D()->showGridImportance(grid);
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ public class WiFi {
|
|||||||
/** try to trigger one scan process */
|
/** try to trigger one scan process */
|
||||||
private static void triggerOneScan() {
|
private static void triggerOneScan() {
|
||||||
|
|
||||||
Log.d("wifi", "triggerOneScan()");
|
//Log.d("wifi", "triggerOneScan()");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(!manager.startScan()) {throw new RuntimeException("Cant start WiFi!");}
|
if(!manager.startScan()) {throw new RuntimeException("Cant start WiFi!");}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
const int8_t pad2 = data[19];
|
const int8_t pad2 = data[19];
|
||||||
if (pad1 != 0 || pad2 != 0) {Debug::error("padding error within BLE scan result");}
|
if (pad1 != 0 || pad2 != 0) {Debug::error("padding error within BLE scan result");}
|
||||||
|
|
||||||
Log::add("BLE", bssid + "; " + std::to_string(static_cast<int>(rssi)));
|
//Log::add("BLE", bssid + "; " + std::to_string(static_cast<int>(rssi)));
|
||||||
|
|
||||||
// call listeners
|
// call listeners
|
||||||
informListeners(BeaconMeasurement(curTS, Beacon(bssid), rssi));
|
informListeners(BeaconMeasurement(curTS, Beacon(bssid), rssi));
|
||||||
|
|||||||
@@ -1,4 +1,91 @@
|
|||||||
#ifndef BLECALIBRATIONDATAMODEL_H
|
#ifndef BLECALIBRATIONDATAMODEL_H
|
||||||
#define BLECALIBRATIONDATAMODEL_H
|
#define BLECALIBRATIONDATAMODEL_H
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <Indoor/sensors/beacon/setup/BeaconFingerprint.h>
|
||||||
|
|
||||||
|
class BLECalibrationDataModel {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/** the file to save the calibration model to */
|
||||||
|
std::string file;
|
||||||
|
|
||||||
|
/** all fingerprints (position -> measurements) within the model */
|
||||||
|
std::vector<BeaconFingerprint> fingerprints;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
BLECalibrationDataModel(const std::string& file) : file(file) {
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<BeaconFingerprint>& getFingerprints() {
|
||||||
|
return fingerprints;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** deserialize the model */
|
||||||
|
void load() {
|
||||||
|
|
||||||
|
// open and check
|
||||||
|
std::ifstream inp(file.c_str());
|
||||||
|
if (inp.bad() || inp.eof() || ! inp.is_open()) { return; }
|
||||||
|
|
||||||
|
// read all entries
|
||||||
|
while (!inp.eof()) {
|
||||||
|
|
||||||
|
// each section starts with [fingerprint]
|
||||||
|
std::string section;
|
||||||
|
inp >> section;
|
||||||
|
if (inp.eof()) {break;}
|
||||||
|
if (section != "[fingerprint]") {throw Exception("error!");}
|
||||||
|
|
||||||
|
// deserialize it
|
||||||
|
BeaconFingerprint bfp;
|
||||||
|
bfp.read(inp);
|
||||||
|
if (bfp.measurements.entries.empty()) {continue;}
|
||||||
|
fingerprints.push_back(bfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inp.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** serialize the model */
|
||||||
|
void save() {
|
||||||
|
|
||||||
|
// open and check
|
||||||
|
std::ofstream out(file.c_str());
|
||||||
|
if (out.bad()) {throw Exception("error while opening " + file + " for write");}
|
||||||
|
|
||||||
|
// write all entries
|
||||||
|
for (const BeaconFingerprint& wfp : fingerprints) {
|
||||||
|
out << "[fingerprint]\n";
|
||||||
|
wfp.write(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
// done
|
||||||
|
out.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** get the fingerprint for the given location. if no fingerprint exists, an empty one is created! */
|
||||||
|
BeaconFingerprint& getFingerprint(const Point3 pos_m) {
|
||||||
|
|
||||||
|
// try to find an existing one
|
||||||
|
for (BeaconFingerprint& bfp : fingerprints) {
|
||||||
|
// get within range of floating-point rounding issues
|
||||||
|
if (bfp.pos_m.getDistance(pos_m) < 0.01) {return bfp;}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a new one and return its reference
|
||||||
|
BeaconFingerprint bfp(pos_m);
|
||||||
|
fingerprints.push_back(bfp);
|
||||||
|
return fingerprints.back();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BLECALIBRATIONDATAMODEL_H
|
#endif // BLECALIBRATIONDATAMODEL_H
|
||||||
|
|||||||
@@ -1,51 +1,51 @@
|
|||||||
#include "WiFiCalibrationScanDialog.h"
|
#include "WiFiCalibrationScanDialog.h"
|
||||||
|
|
||||||
|
|
||||||
WiFiCalibrationScanDialog::WiFiCalibrationScanDialog(WiFiFingerprint& model) : model(model) {
|
WiFiCalibrationScanDialog::WiFiCalibrationScanDialog(WiFiFingerprint& wifiModel, BeaconFingerprint& bleModel) : wifiModel(wifiModel), bleModel(bleModel) {
|
||||||
|
|
||||||
dlg->resize(300, 300);
|
dlg->resize(300, 300);
|
||||||
|
|
||||||
QGridLayout* lay = new QGridLayout(dlg);
|
QGridLayout* lay = new QGridLayout(dlg);
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
|
|
||||||
QPushButton* btnClear = new QPushButton(dlg);
|
QPushButton* btnClear = new QPushButton(dlg);
|
||||||
btnClear->setText("clear");
|
btnClear->setText("clear");
|
||||||
btnClear->connect(btnClear, &QPushButton::clicked, [&] () {clear();});
|
btnClear->connect(btnClear, &QPushButton::clicked, [&] () {clear();});
|
||||||
lay->addWidget(btnClear, row, 0, 1, 1);
|
lay->addWidget(btnClear, row, 0, 1, 1);
|
||||||
|
|
||||||
QPushButton* btnRecord = new QPushButton(dlg);
|
QPushButton* btnRecord = new QPushButton(dlg);
|
||||||
btnRecord->setText("rec");
|
btnRecord->setText("rec");
|
||||||
btnRecord->connect(btnRecord, &QPushButton::clicked, [&] () {startRecord();});
|
btnRecord->connect(btnRecord, &QPushButton::clicked, [&] () {startRecord();});
|
||||||
lay->addWidget(btnRecord, row, 2, 1, 1);
|
lay->addWidget(btnRecord, row, 2, 1, 1);
|
||||||
|
|
||||||
++row;
|
++row;
|
||||||
|
|
||||||
lay->addWidget(new QLabel("point"), row, 0, 1, 1);
|
lay->addWidget(new QLabel("point"), row, 0, 1, 1);
|
||||||
lblPoint = new QLabel();
|
lblPoint = new QLabel();
|
||||||
lay->addWidget(lblPoint, row, 1, 1, 2);
|
lay->addWidget(lblPoint, row, 1, 1, 2);
|
||||||
|
|
||||||
++row;
|
++row;
|
||||||
|
|
||||||
lay->addWidget(new QLabel("stats"), row, 0, 1, 1);
|
lay->addWidget(new QLabel("stats"), row, 0, 1, 1);
|
||||||
lblStats = new QLabel();
|
lblStats = new QLabel();
|
||||||
lay->addWidget(lblStats, row, 1, 1, 2);
|
lay->addWidget(lblStats, row, 1, 1, 2);
|
||||||
|
|
||||||
++row;
|
++row;
|
||||||
|
|
||||||
barProg = new QProgressBar();
|
barProg = new QProgressBar();
|
||||||
lay->addWidget(barProg, row, 0, 1, 3);
|
lay->addWidget(barProg, row, 0, 1, 3);
|
||||||
|
|
||||||
++row;
|
++row;
|
||||||
|
|
||||||
QPushButton* btnCancel = new QPushButton(dlg);
|
QPushButton* btnCancel = new QPushButton(dlg);
|
||||||
btnCancel->setText("cancel");
|
btnCancel->setText("cancel");
|
||||||
btnCancel->connect(btnCancel, &QPushButton::clicked, [&] () {close();});
|
btnCancel->connect(btnCancel, &QPushButton::clicked, [&] () {close();});
|
||||||
lay->addWidget(btnCancel, row, 0, 1, 1);
|
lay->addWidget(btnCancel, row, 0, 1, 1);
|
||||||
|
|
||||||
QPushButton* btnOK = new QPushButton(dlg);
|
QPushButton* btnOK = new QPushButton(dlg);
|
||||||
btnOK->setText("OK");
|
btnOK->setText("OK");
|
||||||
btnOK->connect(btnOK, &QPushButton::clicked, [&] () {save(); close();});
|
btnOK->connect(btnOK, &QPushButton::clicked, [&] () {save(); close();});
|
||||||
lay->addWidget(btnOK, row, 2, 1, 1);
|
lay->addWidget(btnOK, row, 2, 1, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
#include "../sensors/SensorFactory.h"
|
#include "../sensors/SensorFactory.h"
|
||||||
#include "../tools/calibration/WiFiCalibrationDataModel.h"
|
#include "../tools/calibration/WiFiCalibrationDataModel.h"
|
||||||
|
#include "../tools/calibration/BLECalibrationDataModel.h"
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,20 +33,20 @@ private:
|
|||||||
} scan;
|
} scan;
|
||||||
|
|
||||||
/** the measurements model to fill with scan-entries */
|
/** the measurements model to fill with scan-entries */
|
||||||
WiFiFingerprint& model;
|
WiFiFingerprint& wifiModel;
|
||||||
//BeaconFingerprint& blemodel;
|
BeaconFingerprint& bleModel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static void get(WiFiFingerprint& model) {
|
static void get(WiFiFingerprint& wifiModel, BeaconFingerprint& bleModel) {
|
||||||
WiFiCalibrationScanDialog dlg(model);
|
WiFiCalibrationScanDialog dlg(wifiModel, bleModel);
|
||||||
dlg.show();
|
dlg.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** ctor */
|
/** ctor */
|
||||||
WiFiCalibrationScanDialog(WiFiFingerprint& model);
|
WiFiCalibrationScanDialog(WiFiFingerprint& wifiModel, BeaconFingerprint& bleModel);
|
||||||
|
|
||||||
void show() {
|
void show() {
|
||||||
refresh();
|
refresh();
|
||||||
@@ -63,28 +63,39 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_INVOKABLE void refresh() {
|
Q_INVOKABLE void refresh() {
|
||||||
lblPoint->setText(QString(model.pos_m.asString().c_str()));
|
lblPoint->setText(QString(wifiModel.pos_m.asString().c_str()));
|
||||||
lblStats->setText( QString::number(model.measurements.entries.size()) + " RSSI measurements\n" + QString::number(scan.recordsDone) + " scans");
|
lblStats->setText( QString::number(wifiModel.measurements.entries.size()) + " RSSI measurements\n" + QString::number(scan.recordsDone) + " scans");
|
||||||
barProg->setValue(scan.recordsDone);
|
barProg->setValue(scan.recordsDone);
|
||||||
barProg->setMaximum(scan.numRecords);
|
barProg->setMaximum(scan.numRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
model.measurements.entries.clear();
|
wifiModel.measurements.entries.clear();
|
||||||
|
bleModel.measurements.entries.clear();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void startRecord() {
|
void startRecord() {
|
||||||
scan.recordsDone = 0;
|
scan.recordsDone = 0;
|
||||||
|
|
||||||
|
//add wifi
|
||||||
SensorFactory::get().getWiFi().addListener(this);
|
SensorFactory::get().getWiFi().addListener(this);
|
||||||
if (!SensorFactory::get().getWiFi().isRunning()) {
|
if (!SensorFactory::get().getWiFi().isRunning()) {
|
||||||
SensorFactory::get().getWiFi().start();
|
SensorFactory::get().getWiFi().start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//add ble
|
||||||
|
SensorFactory::get().getBLE().addListener(this);
|
||||||
|
if (!SensorFactory::get().getBLE().isRunning()) {
|
||||||
|
SensorFactory::get().getBLE().start();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopRecord() {
|
void stopRecord() {
|
||||||
SensorFactory::get().getWiFi().removeListener(this);
|
SensorFactory::get().getWiFi().removeListener(this);
|
||||||
|
SensorFactory::get().getBLE().removeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onSensorData(Sensor<WiFiMeasurements>* sensor, const Timestamp ts, const WiFiMeasurements& data) override {
|
virtual void onSensorData(Sensor<WiFiMeasurements>* sensor, const Timestamp ts, const WiFiMeasurements& data) override {
|
||||||
@@ -92,7 +103,7 @@ private:
|
|||||||
(void) ts;
|
(void) ts;
|
||||||
++scan.recordsDone;
|
++scan.recordsDone;
|
||||||
if (scan.recordsDone >= scan.numRecords) {stopRecord();}
|
if (scan.recordsDone >= scan.numRecords) {stopRecord();}
|
||||||
model.measurements.entries.insert(model.measurements.entries.end(), data.entries.begin(), data.entries.end());
|
wifiModel.measurements.entries.insert(wifiModel.measurements.entries.end(), data.entries.begin(), data.entries.end());
|
||||||
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +111,7 @@ private:
|
|||||||
virtual void onSensorData(Sensor<BeaconMeasurement>* sensor, const Timestamp ts, const BeaconMeasurement& data) override {
|
virtual void onSensorData(Sensor<BeaconMeasurement>* sensor, const Timestamp ts, const BeaconMeasurement& data) override {
|
||||||
(void) sensor;
|
(void) sensor;
|
||||||
(void) ts;
|
(void) ts;
|
||||||
|
bleModel.measurements.entries.push_back(data);
|
||||||
|
|
||||||
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,32 +20,32 @@
|
|||||||
|
|
||||||
MapView2D::MapView2D(QWidget *parent) : QWidget(parent) {
|
MapView2D::MapView2D(QWidget *parent) : QWidget(parent) {
|
||||||
|
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
setRenderHeight(0);
|
setRenderHeight(0);
|
||||||
|
|
||||||
|
|
||||||
colorPoints = new ColorPoints2D();
|
colorPoints = new ColorPoints2D();
|
||||||
elementsB.push_back(colorPoints);
|
elementsB.push_back(colorPoints);
|
||||||
|
|
||||||
pathToDest = new Path2D();
|
pathToDest = new Path2D();
|
||||||
pathToDest->setColor(Qt::blue);
|
pathToDest->setColor(Qt::blue);
|
||||||
pathToDest->setWidth(10);
|
pathToDest->setWidth(10);
|
||||||
elementsB.push_back(pathToDest);
|
elementsB.push_back(pathToDest);
|
||||||
|
|
||||||
pathWalked = new Path2D();
|
pathWalked = new Path2D();
|
||||||
pathToDest->setColor(Qt::black);
|
pathToDest->setColor(Qt::black);
|
||||||
pathToDest->setWidth(5);
|
pathToDest->setWidth(5);
|
||||||
elementsB.push_back(pathWalked);
|
elementsB.push_back(pathWalked);
|
||||||
|
|
||||||
// buttons
|
// buttons
|
||||||
//menu = new QWidget(this);
|
//menu = new QWidget(this);
|
||||||
QGridLayout* lay = new QGridLayout(this);
|
QGridLayout* lay = new QGridLayout(this);
|
||||||
int row = 0;
|
int row = 0;
|
||||||
|
|
||||||
|
|
||||||
lay->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding), row, 0, 1, 1);
|
lay->addItem(new QSpacerItem(0,0,QSizePolicy::Minimum,QSizePolicy::Expanding), row, 0, 1, 1);
|
||||||
|
|
||||||
++ row;
|
++ row;
|
||||||
|
|
||||||
// // map-layer slider
|
// // map-layer slider
|
||||||
// sldLayer = new QSlider();
|
// sldLayer = new QSlider();
|
||||||
@@ -54,65 +54,65 @@ MapView2D::MapView2D(QWidget *parent) : QWidget(parent) {
|
|||||||
// connect(sldLayer, &QSlider::sliderReleased, this, &MapView2D::onLayerSelect);
|
// connect(sldLayer, &QSlider::sliderReleased, this, &MapView2D::onLayerSelect);
|
||||||
// lay->addWidget(sldLayer, row, 0, 1, 1);
|
// lay->addWidget(sldLayer, row, 0, 1, 1);
|
||||||
|
|
||||||
// show/hide button
|
// show/hide button
|
||||||
const int bs = UIHelper::getButtonSize(this);
|
const int bs = UIHelper::getButtonSize(this);
|
||||||
btnColorPoints = new QPushButton(Icons::getIcon("dots", bs), "");
|
btnColorPoints = new QPushButton(Icons::getIcon("dots", bs), "");
|
||||||
btnColorPoints->connect(btnColorPoints, &QPushButton::clicked, [&] () {colorPoints->setVisible(!colorPoints->isVisible()); emit update();} );
|
btnColorPoints->connect(btnColorPoints, &QPushButton::clicked, [&] () {colorPoints->setVisible(!colorPoints->isVisible()); emit update();} );
|
||||||
lay->addWidget(btnColorPoints, row, 0, 1, 1);
|
lay->addWidget(btnColorPoints, row, 0, 1, 1);
|
||||||
|
|
||||||
btnLayerMinus = new QPushButton("-");
|
btnLayerMinus = new QPushButton("-");
|
||||||
connect(btnLayerMinus, &QPushButton::clicked, this, &MapView2D::onLayerMinus);
|
connect(btnLayerMinus, &QPushButton::clicked, this, &MapView2D::onLayerMinus);
|
||||||
lay->addWidget(btnLayerMinus, row, 1, 1, 1);
|
lay->addWidget(btnLayerMinus, row, 1, 1, 1);
|
||||||
|
|
||||||
btnLayerPlus = new QPushButton("+");
|
btnLayerPlus = new QPushButton("+");
|
||||||
connect(btnLayerPlus, &QPushButton::clicked, this, &MapView2D::onLayerPlus);
|
connect(btnLayerPlus, &QPushButton::clicked, this, &MapView2D::onLayerPlus);
|
||||||
lay->addWidget(btnLayerPlus, row, 2, 1, 1);
|
lay->addWidget(btnLayerPlus, row, 2, 1, 1);
|
||||||
|
|
||||||
|
|
||||||
// start with invisible particles. speeds things up a bit
|
// start with invisible particles. speeds things up a bit
|
||||||
colorPoints->setVisible(false);
|
colorPoints->setVisible(false);
|
||||||
|
|
||||||
// we want to receive pinch gestures
|
// we want to receive pinch gestures
|
||||||
//setAttribute(Qt::WA_AcceptTouchEvents, true);
|
//setAttribute(Qt::WA_AcceptTouchEvents, true);
|
||||||
grabGesture(Qt::PinchGesture);
|
grabGesture(Qt::PinchGesture);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::onLayerSelect() {
|
void MapView2D::onLayerSelect() {
|
||||||
setRenderHeight(sldLayer->value());
|
setRenderHeight(sldLayer->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::onLayerMinus() {
|
void MapView2D::onLayerMinus() {
|
||||||
if (layerHeight_m <= 0) {return;}
|
if (layerHeight_m <= 0) {return;}
|
||||||
layerHeight_m -= 1;
|
layerHeight_m -= 1;
|
||||||
setRenderHeight(layerHeight_m);
|
setRenderHeight(layerHeight_m);
|
||||||
}
|
}
|
||||||
void MapView2D::onLayerPlus() {
|
void MapView2D::onLayerPlus() {
|
||||||
if (layerHeight_m >= 16) {return;}
|
if (layerHeight_m >= 16) {return;}
|
||||||
layerHeight_m += 1;
|
layerHeight_m += 1;
|
||||||
setRenderHeight(layerHeight_m);
|
setRenderHeight(layerHeight_m);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::setMap(WiFiCalibrationDataModel* mdl, Floorplan::IndoorMap* map) {
|
void MapView2D::setMap(WiFiCalibrationDataModel* wifiMdl, BLECalibrationDataModel* bleMdl, Floorplan::IndoorMap* map) {
|
||||||
|
|
||||||
for (Floorplan::Floor* floor : map->floors) {
|
for (Floorplan::Floor* floor : map->floors) {
|
||||||
Floor2D* f = new Floor2D(floor);
|
Floor2D* f = new Floor2D(floor);
|
||||||
elementsA.push_back(f);
|
elementsA.push_back(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
wifiCalib = new WiFiCalibTool(mdl, map);
|
wifiCalib = new WiFiCalibTool(wifiMdl, bleMdl, map);
|
||||||
elementsB.push_back(wifiCalib);
|
elementsB.push_back(wifiCalib);
|
||||||
|
|
||||||
const BBox3 bbox3 = FloorplanHelper::getBBox(map);
|
const BBox3 bbox3 = FloorplanHelper::getBBox(map);
|
||||||
const BBox2 bbox2 = BBox2(bbox3.getMin().xy(), bbox3.getMax().xy());
|
const BBox2 bbox2 = BBox2(bbox3.getMin().xy(), bbox3.getMax().xy());
|
||||||
|
|
||||||
scaler.setMapBBox(bbox2);
|
scaler.setMapBBox(bbox2);
|
||||||
scaler.setCenterM(Point2(bbox2.getCenter().x, bbox2.getCenter().y));
|
scaler.setCenterM(Point2(bbox2.getCenter().x, bbox2.getCenter().y));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::showParticles(const std::vector<SMC::Particle<GridBased::MyState>>* particles) {
|
void MapView2D::showParticles(const std::vector<SMC::Particle<GridBased::MyState>>* particles) {
|
||||||
this->colorPoints->setFromParticles(*particles);
|
this->colorPoints->setFromParticles(*particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::showParticles(const std::vector<SMC::Particle<MeshBased::MyState>>* particles) {
|
void MapView2D::showParticles(const std::vector<SMC::Particle<MeshBased::MyState>>* particles) {
|
||||||
@@ -120,130 +120,130 @@ void MapView2D::showParticles(const std::vector<SMC::Particle<MeshBased::MyState
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::setCurrentEstimation(const Point3 pos_m, const Point3 dir) {
|
void MapView2D::setCurrentEstimation(const Point3 pos_m, const Point3 dir) {
|
||||||
(void) dir;
|
(void) dir;
|
||||||
setRenderHeight(pos_m.z);
|
setRenderHeight(pos_m.z);
|
||||||
scaler.setCenterM(pos_m.xy());
|
scaler.setCenterM(pos_m.xy());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::setRenderHeight(const float height_m) {
|
void MapView2D::setRenderHeight(const float height_m) {
|
||||||
renderParams.clip.aboveHeight_m = height_m + 1.5;
|
renderParams.clip.aboveHeight_m = height_m + 1.5;
|
||||||
renderParams.clip.belowHeight_m = height_m - 1.5;
|
renderParams.clip.belowHeight_m = height_m - 1.5;
|
||||||
emit update();
|
emit update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::showGridImportance(Grid<MyGridNode>* grid) {
|
void MapView2D::showGridImportance(Grid<MyGridNode>* grid) {
|
||||||
colorPoints->showGridImportance(grid);
|
colorPoints->showGridImportance(grid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::resizeEvent(QResizeEvent* evt) {
|
void MapView2D::resizeEvent(QResizeEvent* evt) {
|
||||||
(void) evt;
|
(void) evt;
|
||||||
int s = UIHelper::getButtonSize(this->parent()) * 1.5;
|
int s = UIHelper::getButtonSize(this->parent()) * 1.5;
|
||||||
//sldLayer->setMinimumHeight(s);
|
//sldLayer->setMinimumHeight(s);
|
||||||
//sldLayer->setMinimum(0);
|
//sldLayer->setMinimum(0);
|
||||||
//sldLayer->setMaximum(16);
|
//sldLayer->setMaximum(16);
|
||||||
btnColorPoints->setMinimumHeight(s);
|
btnColorPoints->setMinimumHeight(s);
|
||||||
btnColorPoints->setMinimumWidth(s);
|
btnColorPoints->setMinimumWidth(s);
|
||||||
btnLayerMinus->setMinimumHeight(s);
|
btnLayerMinus->setMinimumHeight(s);
|
||||||
btnLayerMinus->setMinimumWidth(s);
|
btnLayerMinus->setMinimumWidth(s);
|
||||||
btnLayerPlus->setMinimumHeight(s);
|
btnLayerPlus->setMinimumHeight(s);
|
||||||
btnLayerPlus->setMinimumWidth(s);
|
btnLayerPlus->setMinimumWidth(s);
|
||||||
|
|
||||||
scaler.setScreenSize(width(), height());
|
scaler.setScreenSize(width(), height());
|
||||||
scaler.setScale( UIHelper::isLarge(this->parent()) ? 2 : 1 );
|
scaler.setScale( UIHelper::isLarge(this->parent()) ? 2 : 1 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::mousePressEvent(QMouseEvent* evt) {
|
void MapView2D::mousePressEvent(QMouseEvent* evt) {
|
||||||
move.startCenter_px = scaler.getCenterPX();
|
move.startCenter_px = scaler.getCenterPX();
|
||||||
move.startMouse_px = Point2(evt->x(), evt->y());
|
move.startMouse_px = Point2(evt->x(), evt->y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::mouseMoveEvent(QMouseEvent* evt) {
|
void MapView2D::mouseMoveEvent(QMouseEvent* evt) {
|
||||||
Point2 pt(evt->x(), evt->y());
|
Point2 pt(evt->x(), evt->y());
|
||||||
pt -= move.startMouse_px;
|
pt -= move.startMouse_px;
|
||||||
pt.x = -pt.x;
|
pt.x = -pt.x;
|
||||||
pt += move.startCenter_px;
|
pt += move.startCenter_px;
|
||||||
scaler.setCenterPX(pt);
|
scaler.setCenterPX(pt);
|
||||||
emit update();
|
emit update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::mouseReleaseEvent(QMouseEvent* evt) {
|
void MapView2D::mouseReleaseEvent(QMouseEvent* evt) {
|
||||||
|
|
||||||
if (!wifiCalib) {return;}
|
if (!wifiCalib) {return;}
|
||||||
|
|
||||||
const Point2 p1(evt->x(), evt->y());
|
const Point2 p1(evt->x(), evt->y());
|
||||||
|
|
||||||
// fingerprint node pressed?
|
// fingerprint node pressed?
|
||||||
const int fpSize = UIHelper::isLarge(this->parent()) ? (40) : (25);
|
const int fpSize = UIHelper::isLarge(this->parent()) ? (40) : (25);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
for (const Point2 p2 : wifiCalib->getNodes()) {
|
for (const Point2 p2 : wifiCalib->getNodes()) {
|
||||||
const float dist = p1.getDistance(p2);
|
const float dist = p1.getDistance(p2);
|
||||||
if (dist < fpSize) { wifiCalib->selectNode(idx); emit update(); break; }
|
if (dist < fpSize) { wifiCalib->selectNode(idx); emit update(); break; }
|
||||||
++idx;
|
++idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::wheelEvent(QWheelEvent* event) {
|
void MapView2D::wheelEvent(QWheelEvent* event) {
|
||||||
if (event->delta() < 0) {
|
if (event->delta() < 0) {
|
||||||
scaler.mulScale(0.5);
|
scaler.mulScale(0.5);
|
||||||
emit update();
|
emit update();
|
||||||
} else {
|
} else {
|
||||||
scaler.mulScale(2.0);
|
scaler.mulScale(2.0);
|
||||||
emit update();
|
emit update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView2D::paintEvent(QPaintEvent*) {
|
void MapView2D::paintEvent(QPaintEvent*) {
|
||||||
|
|
||||||
QPainter qp(this);
|
QPainter qp(this);
|
||||||
|
|
||||||
// clear
|
// clear
|
||||||
qp.fillRect(0, 0, width(), height(), Qt::white);
|
qp.fillRect(0, 0, width(), height(), Qt::white);
|
||||||
|
|
||||||
// render elements
|
// render elements
|
||||||
for (Renderable2D* r : elementsA) {r->render(qp, scaler, renderParams);}
|
for (Renderable2D* r : elementsA) {r->render(qp, scaler, renderParams);}
|
||||||
for (Renderable2D* r : elementsB) {r->render(qp, scaler, renderParams);}
|
for (Renderable2D* r : elementsB) {r->render(qp, scaler, renderParams);}
|
||||||
|
|
||||||
qp.end();
|
qp.end();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapView2D::event(QEvent *event) {
|
bool MapView2D::event(QEvent *event) {
|
||||||
|
|
||||||
switch (event->type()) {
|
switch (event->type()) {
|
||||||
case QEvent::Gesture:
|
case QEvent::Gesture:
|
||||||
return gestureEvent(static_cast<QGestureEvent*>(event));
|
return gestureEvent(static_cast<QGestureEvent*>(event));
|
||||||
|
|
||||||
case QEvent::TouchBegin:
|
case QEvent::TouchBegin:
|
||||||
case QEvent::TouchUpdate:
|
case QEvent::TouchUpdate:
|
||||||
case QEvent::TouchEnd:
|
case QEvent::TouchEnd:
|
||||||
|
|
||||||
// prevent [additional] mouse events for undetected gestures [more than 1 finger]
|
// prevent [additional] mouse events for undetected gestures [more than 1 finger]
|
||||||
// TODO: not yet stable... improvements?
|
// TODO: not yet stable... improvements?
|
||||||
if (static_cast<QTouchEvent*>(event)->touchPoints().count() == 2) {return true;}
|
if (static_cast<QTouchEvent*>(event)->touchPoints().count() == 2) {return true;}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// event not consumed. bubble it to following stages.
|
// event not consumed. bubble it to following stages.
|
||||||
// this will e.g. generate mouseMoveEvent etc.
|
// this will e.g. generate mouseMoveEvent etc.
|
||||||
return QWidget::event(event);
|
return QWidget::event(event);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapView2D::gestureEvent(QGestureEvent *event) {
|
bool MapView2D::gestureEvent(QGestureEvent *event) {
|
||||||
|
|
||||||
if (QGesture* pinch = event->gesture(Qt::PinchGesture)) {
|
if (QGesture* pinch = event->gesture(Qt::PinchGesture)) {
|
||||||
const QPinchGesture* pg = static_cast<QPinchGesture *>(pinch);
|
const QPinchGesture* pg = static_cast<QPinchGesture *>(pinch);
|
||||||
scaler.mulScale(pg->scaleFactor());
|
scaler.mulScale(pg->scaleFactor());
|
||||||
emit update();
|
emit update();
|
||||||
return true; // event consumed
|
return true; // event consumed
|
||||||
}
|
}
|
||||||
|
|
||||||
// event not consumed
|
// event not consumed
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
#include "nav/grid/State.h"
|
#include "nav/grid/State.h"
|
||||||
#include "nav/mesh/State.h"
|
#include "nav/mesh/State.h"
|
||||||
|
|
||||||
|
#include "../tools/calibration/BLECalibrationDataModel.h"
|
||||||
|
|
||||||
namespace Floorplan {
|
namespace Floorplan {
|
||||||
class IndoorMap;
|
class IndoorMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> class Grid;
|
template <typename T> class Grid;
|
||||||
@@ -30,7 +32,7 @@ class Path2D;
|
|||||||
|
|
||||||
template <typename T> class DijkstraPath;
|
template <typename T> class DijkstraPath;
|
||||||
namespace SMC {
|
namespace SMC {
|
||||||
template <typename T> class Particle;
|
template <typename T> class Particle;
|
||||||
}
|
}
|
||||||
class MyState;
|
class MyState;
|
||||||
|
|
||||||
@@ -39,73 +41,73 @@ class WiFiCalibrationDataModel;
|
|||||||
|
|
||||||
class MapView2D : public QWidget {
|
class MapView2D : public QWidget {
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::vector<Renderable2D*> elementsA;
|
std::vector<Renderable2D*> elementsA;
|
||||||
std::vector<Renderable2D*> elementsB;
|
std::vector<Renderable2D*> elementsB;
|
||||||
|
|
||||||
ColorPoints2D* colorPoints = nullptr;
|
ColorPoints2D* colorPoints = nullptr;
|
||||||
Path2D* pathToDest = nullptr;
|
Path2D* pathToDest = nullptr;
|
||||||
Path2D* pathWalked = nullptr;
|
Path2D* pathWalked = nullptr;
|
||||||
WiFiCalibTool* wifiCalib = nullptr;
|
WiFiCalibTool* wifiCalib = nullptr;
|
||||||
|
|
||||||
Scaler2D scaler;
|
Scaler2D scaler;
|
||||||
RenderParams2D renderParams;
|
RenderParams2D renderParams;
|
||||||
float layerHeight_m = 0;
|
float layerHeight_m = 0;
|
||||||
|
|
||||||
struct Move {
|
struct Move {
|
||||||
Point2 startCenter_px;
|
Point2 startCenter_px;
|
||||||
Point2 startMouse_px;
|
Point2 startMouse_px;
|
||||||
} move;
|
} move;
|
||||||
|
|
||||||
QWidget* menu = nullptr;
|
QWidget* menu = nullptr;
|
||||||
QSlider* sldLayer = nullptr;
|
QSlider* sldLayer = nullptr;
|
||||||
QPushButton* btnColorPoints = nullptr;
|
QPushButton* btnColorPoints = nullptr;
|
||||||
QPushButton* btnLayerPlus = nullptr;
|
QPushButton* btnLayerPlus = nullptr;
|
||||||
QPushButton* btnLayerMinus = nullptr;
|
QPushButton* btnLayerMinus = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit MapView2D(QWidget *parent = 0);
|
explicit MapView2D(QWidget *parent = 0);
|
||||||
|
|
||||||
/** set the to-be-shown map */
|
/** set the to-be-shown map */
|
||||||
void setMap(WiFiCalibrationDataModel* mdl, Floorplan::IndoorMap* map);
|
void setMap(WiFiCalibrationDataModel* wifiMdl, BLECalibrationDataModel* bleMdl, Floorplan::IndoorMap* map);
|
||||||
|
|
||||||
/** show importance factors for the grid */
|
/** show importance factors for the grid */
|
||||||
void showGridImportance(Grid<MyGridNode>* grid);
|
void showGridImportance(Grid<MyGridNode>* grid);
|
||||||
|
|
||||||
/** set the height-slice to be visible */
|
/** set the height-slice to be visible */
|
||||||
void setRenderHeight(const float height_m);
|
void setRenderHeight(const float height_m);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** set the path to the destination MUST BE CALLED FROM THE MAIN THREAD */
|
/** set the path to the destination MUST BE CALLED FROM THE MAIN THREAD */
|
||||||
void setPathToDestination(const std::vector<Point3>& path);
|
void setPathToDestination(const std::vector<Point3>& path);
|
||||||
|
|
||||||
/** set the path to disply. MUST BE CALLED FROM THE MAIN THREAD */
|
/** set the path to disply. MUST BE CALLED FROM THE MAIN THREAD */
|
||||||
template <typename Node> void setPathToDestination(const DijkstraPath<Node>* path) {this->pathToDest->set(*path);}
|
template <typename Node> void setPathToDestination(const DijkstraPath<Node>* path) {this->pathToDest->set(*path);}
|
||||||
|
|
||||||
/** set the path to disply. MUST BE CALLED FROM THE MAIN THREAD*/
|
/** set the path to disply. MUST BE CALLED FROM THE MAIN THREAD*/
|
||||||
Q_INVOKABLE void setPathToDestination(const void* path) { setPathToDestination( (const DijkstraPath<MyGridNode>*) path); }
|
Q_INVOKABLE void setPathToDestination(const void* path) { setPathToDestination( (const DijkstraPath<MyGridNode>*) path); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** set the walked path. MUST BE CALLED FROM THE MAIN THREAD */
|
/** set the walked path. MUST BE CALLED FROM THE MAIN THREAD */
|
||||||
void setPathWalked(const std::vector<Point3>& path) {this->pathWalked->set(path);}
|
void setPathWalked(const std::vector<Point3>& path) {this->pathWalked->set(path);}
|
||||||
|
|
||||||
/** set the walked path. MUST BE CALLED FROM THE MAIN THREAD */
|
/** set the walked path. MUST BE CALLED FROM THE MAIN THREAD */
|
||||||
Q_INVOKABLE void setPathWalked(const void* path) { this->pathWalked->set( *((const std::vector<Point3>*) path)); }
|
Q_INVOKABLE void setPathWalked(const void* path) { this->pathWalked->set( *((const std::vector<Point3>*) path)); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** NOTE: must be called from Qt's main thread! */
|
/** NOTE: must be called from Qt's main thread! */
|
||||||
Q_INVOKABLE void showParticles(const void* particles) {
|
Q_INVOKABLE void showParticles(const void* particles) {
|
||||||
showParticles((const std::vector<SMC::Particle<MeshBased::MyState>>*) particles);
|
showParticles((const std::vector<SMC::Particle<MeshBased::MyState>>*) particles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** NOTE: must be called from Qt's main thread! */
|
/** NOTE: must be called from Qt's main thread! */
|
||||||
void showParticles(const std::vector<SMC::Particle<GridBased::MyState>>* particles);
|
void showParticles(const std::vector<SMC::Particle<GridBased::MyState>>* particles);
|
||||||
|
|
||||||
|
|
||||||
@@ -113,31 +115,31 @@ public:
|
|||||||
void showParticles(const std::vector<SMC::Particle<MeshBased::MyState>>* particles);
|
void showParticles(const std::vector<SMC::Particle<MeshBased::MyState>>* particles);
|
||||||
|
|
||||||
|
|
||||||
/** set the currently estimated position */
|
/** set the currently estimated position */
|
||||||
void setCurrentEstimation(const Point3 pos, const Point3 dir);
|
void setCurrentEstimation(const Point3 pos, const Point3 dir);
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
|
|
||||||
void onLayerSelect();
|
void onLayerSelect();
|
||||||
void onLayerPlus();
|
void onLayerPlus();
|
||||||
void onLayerMinus();
|
void onLayerMinus();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent*);
|
void resizeEvent(QResizeEvent*);
|
||||||
|
|
||||||
void paintEvent(QPaintEvent*);
|
void paintEvent(QPaintEvent*);
|
||||||
|
|
||||||
void mousePressEvent(QMouseEvent*);
|
void mousePressEvent(QMouseEvent*);
|
||||||
void mouseMoveEvent(QMouseEvent*);
|
void mouseMoveEvent(QMouseEvent*);
|
||||||
void mouseReleaseEvent(QMouseEvent*);
|
void mouseReleaseEvent(QMouseEvent*);
|
||||||
void wheelEvent(QWheelEvent*);
|
void wheelEvent(QWheelEvent*);
|
||||||
|
|
||||||
bool event(QEvent*);
|
bool event(QEvent*);
|
||||||
bool gestureEvent(QGestureEvent *event);
|
bool gestureEvent(QGestureEvent *event);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,91 +20,96 @@
|
|||||||
#include "../../../sensors/SensorFactory.h"
|
#include "../../../sensors/SensorFactory.h"
|
||||||
|
|
||||||
struct WiFiCalibPoint {
|
struct WiFiCalibPoint {
|
||||||
std::string name; // title
|
std::string name; // title
|
||||||
Point3 pos_m; // map position + smartphone height
|
Point3 pos_m; // map position + smartphone height
|
||||||
Point2 pos_px; // screen position
|
Point2 pos_px; // screen position
|
||||||
WiFiCalibPoint(const std::string& name, const Point3 pos_m, const Point2 pos_px) : name(name), pos_m(pos_m), pos_px(pos_px) {;}
|
WiFiCalibPoint(const std::string& name, const Point3 pos_m, const Point2 pos_px) : name(name), pos_m(pos_m), pos_px(pos_px) {;}
|
||||||
WiFiCalibPoint() {;}
|
WiFiCalibPoint() {;}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* helper for wifi calibration
|
* helper for wifi calibration
|
||||||
|
* TODO: Make this generic for BLE and WiFI
|
||||||
*/
|
*/
|
||||||
class WiFiCalibTool : public Renderable2D {
|
class WiFiCalibTool : public Renderable2D {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
WiFiCalibrationDataModel* mdl;
|
WiFiCalibrationDataModel* wifiMdl;
|
||||||
Floorplan::IndoorMap* map;
|
BLECalibrationDataModel* bleMdl;
|
||||||
|
|
||||||
std::vector<WiFiCalibPoint> currentlyVisible;
|
Floorplan::IndoorMap* map;
|
||||||
WiFiCalibPoint currentlySelected;
|
|
||||||
|
std::vector<WiFiCalibPoint> currentlyVisible;
|
||||||
|
WiFiCalibPoint currentlySelected;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** ctor */
|
/** ctor */
|
||||||
WiFiCalibTool(WiFiCalibrationDataModel* mdl, Floorplan::IndoorMap* map) : mdl(mdl), map(map) {
|
WiFiCalibTool(WiFiCalibrationDataModel* wifiMdl, BLECalibrationDataModel* bleMdl, Floorplan::IndoorMap* map) : wifiMdl(wifiMdl), bleMdl(bleMdl), map(map) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void selectNode(const int idx) {
|
virtual void selectNode(const int idx) {
|
||||||
currentlySelected = currentlyVisible[idx];
|
currentlySelected = currentlyVisible[idx];
|
||||||
showCalib(currentlySelected);
|
showCalib(currentlySelected);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** get all selectable caliration nodes */
|
/** get all selectable caliration nodes */
|
||||||
virtual std::vector<Point2> getNodes() const {
|
virtual std::vector<Point2> getNodes() const {
|
||||||
std::vector<Point2> pts;
|
std::vector<Point2> pts;
|
||||||
for (const WiFiCalibPoint& cp : currentlyVisible) {pts.push_back(cp.pos_px);}
|
for (const WiFiCalibPoint& cp : currentlyVisible) {pts.push_back(cp.pos_px);}
|
||||||
return pts;
|
return pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void doRender(QPainter& qp, const Scaler2D& s, const RenderParams2D& r) override {
|
void doRender(QPainter& qp, const Scaler2D& s, const RenderParams2D& r) override {
|
||||||
|
|
||||||
currentlyVisible.clear();
|
currentlyVisible.clear();
|
||||||
const QFont font("Arial", 10);
|
const QFont font("Arial", 10);
|
||||||
qp.setFont(font);
|
qp.setFont(font);
|
||||||
|
|
||||||
// get all fingerprint-locations that are currently visible on the 2D map
|
// get all fingerprint-locations that are currently visible on the 2D map
|
||||||
for (const Floorplan::Floor* floor : map->floors) {
|
for (const Floorplan::Floor* floor : map->floors) {
|
||||||
for (const Floorplan::FingerprintLocation* fpLoc : floor->fpLocations) {
|
for (const Floorplan::FingerprintLocation* fpLoc : floor->fpLocations) {
|
||||||
|
|
||||||
//const Point3 p = beacon->pos + Point3(0,0,floor->atHeight) + Point3(0,0,Settings::smartphoneAboveGround);
|
//const Point3 p = beacon->pos + Point3(0,0,floor->atHeight) + Point3(0,0,Settings::smartphoneAboveGround);
|
||||||
const Point3 p = fpLoc->getPosition(*floor); // is already above ground as configured within the map
|
const Point3 p = fpLoc->getPosition(*floor); // is already above ground as configured within the map
|
||||||
const Point2 pt = s.mapToScreen(p.xy());
|
const Point2 pt = s.mapToScreen(p.xy());
|
||||||
|
|
||||||
if (floor->atHeight < r.clip.belowHeight_m) {continue;}
|
if (floor->atHeight < r.clip.belowHeight_m) {continue;}
|
||||||
if (floor->atHeight > r.clip.aboveHeight_m) {continue;}
|
if (floor->atHeight > r.clip.aboveHeight_m) {continue;}
|
||||||
|
|
||||||
const WiFiCalibPoint cp(fpLoc->name, p, pt);
|
const WiFiCalibPoint cp(fpLoc->name, p, pt);
|
||||||
currentlyVisible.push_back(cp);
|
currentlyVisible.push_back(cp);
|
||||||
|
|
||||||
const WiFiFingerprint& fp = mdl->getFingerprint(cp.pos_m);
|
const WiFiFingerprint& wfp = wifiMdl->getFingerprint(cp.pos_m);
|
||||||
const QString txt1(fpLoc->name.c_str());
|
const BeaconFingerprint& bfp = bleMdl->getFingerprint(cp.pos_m);
|
||||||
const QString txt2 = QString::number(fp.measurements.entries.size());
|
|
||||||
qp.setPen(Qt::black);
|
|
||||||
|
|
||||||
if (currentlySelected.name == cp.name) {
|
const QString txt1(fpLoc->name.c_str());
|
||||||
qp.setBrush(Qt::blue);
|
const QString txt2 = QString::number(wfp.measurements.entries.size());
|
||||||
} else {
|
qp.setPen(Qt::black);
|
||||||
qp.setBrush(Qt::NoBrush);
|
|
||||||
}
|
|
||||||
|
|
||||||
//FONT SIZE??
|
if (currentlySelected.name == cp.name) {
|
||||||
|
qp.setBrush(Qt::blue);
|
||||||
|
} else {
|
||||||
|
qp.setBrush(Qt::NoBrush);
|
||||||
|
}
|
||||||
|
|
||||||
|
//FONT SIZE??
|
||||||
|
|
||||||
|
|
||||||
int s = 20;
|
int s = 20;
|
||||||
qp.drawEllipse(pt.x-s, pt.y-s, s*2, s*2);
|
qp.drawEllipse(pt.x-s, pt.y-s, s*2, s*2);
|
||||||
qp.drawText(pt.x+s*2, pt.y-s, txt1);
|
qp.drawText(pt.x+s*2, pt.y-s, txt1);
|
||||||
qp.drawText(pt.x+s*2, pt.y+s, txt2);
|
qp.drawText(pt.x+s*2, pt.y+s, txt2);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -113,18 +118,21 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void showCalib(const WiFiCalibPoint& cp) {
|
void showCalib(const WiFiCalibPoint& cp) {
|
||||||
|
|
||||||
// get (or create an empty one) the fingerprint for this location
|
// get (or create an empty one) the fingerprint for this location
|
||||||
WiFiFingerprint& fp = mdl->getFingerprint(cp.pos_m);
|
WiFiFingerprint& wfp = wifiMdl->getFingerprint(cp.pos_m);
|
||||||
|
BeaconFingerprint& bfp = bleMdl->getFingerprint(cp.pos_m);
|
||||||
|
|
||||||
// edit it (blocking!)
|
// edit it (blocking!)
|
||||||
WiFiCalibrationScanDialog::get(fp);
|
WiFiCalibrationScanDialog::get(wfp, bfp);
|
||||||
|
|
||||||
// save the model
|
// save the model
|
||||||
mdl->save();
|
wifiMdl->save();
|
||||||
|
|
||||||
}
|
//save bluetooth model here!
|
||||||
|
bleMdl->save();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user