This repository has been archived on 2020-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
Files
YASMIN/Controller.cpp
toni 625f5fe04d updated sensors and filter to current code version
removed KLib stuff
added new activity
filter is uncommand!
at the moment, the app is not able to load new maps and breaks using old maps
2018-07-12 18:39:27 +02:00

372 lines
12 KiB
C++

#include "Controller.h"
#include "ui/map/3D/MapView3D.h"
#include "ui/map/2D/MapView2D.h"
#include "ui/menu/MainMenu.h"
#include "ui/MainWindow.h"
#include "ui/dialog/LoadSetupDialog.h"
#include "ui/debug/SensorDataWidget.h"
#include <Indoor/grid/factory/v2/GridFactory.h>
#include <Indoor/grid/factory/v2/Importance.h>
#include <Indoor/navMesh/NavMesh.h>
#include <Indoor/navMesh/NavMeshFactory.h>
#include <Indoor/floorplan/v2/Floorplan.h>
#include <Indoor/floorplan/v2/FloorplanReader.h>
#include <Indoor/floorplan/v2/FloorplanHelper.h>
#include <Indoor/sensors/radio/WiFiGridEstimator.h>
#include <Indoor/sensors/radio/setup/WiFiOptimizerLogDistCeiling.h>
#include <Indoor/sensors/radio/model/WiFiModel.h>
#include <Indoor/Assertions.h>
#include "ui/LoggerUI.h"
#include <Indoor/misc/log/LoggerComposite.h>
#include <Indoor/misc/log/LoggerCOUT.h>
#include <Indoor/misc/log/LoggerAndroid.h>
#include "sensors/dummy/SensorFactoryDummy.h"
#include "sensors/android/SensorFactoryAndroid.h"
#include "sensors/offline/SensorFactoryOffline.h"
#include "sensors/SensorWriter.h"
#include "tools/calibration/WiFiCalibrationDataModel.h"
#include "nav/NavController.h"
#include "nav/grid/NavControllerGrid.h"
#include "nav/mesh/NavControllerMesh.h"
Controller::Controller() {
// OpenGL setup
// MUST happen before anything gets visible (= gets initialized)
QSurfaceFormat format;
format.setDepthBufferSize(16);
QSurfaceFormat::setDefaultFormat(format);
// configure the to-be-used sensor factory
//SensorFactory::set(new SensorFactoryDummy());
//SensorFactory::set(new SensorFactoryOffline("/apps/android/workspace/YASMIN_DATA/offline/gyroacctestingfrank/nexus6/kleinerKreis_216steps_6runden_telefongerade.csv"));
//SensorFactory::set(new SensorFactoryOffline("/apps/android/workspace/YASMIN_DATA/offline/gyroacctestingfrank/s3mini/kleinerKreis_225steps_6runden_telefongerade.csv"));
//SensorFactory::set(new SensorFactoryOffline("/apps/android/workspace/YASMIN_DATA/offline/gyroacctestingfrank/s4/kleinerKreis_220steps_6runden_telefongeneigt.csv"));
//SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "bergwerk/path3/nexus/vor/1454782562231.csv"));
//SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "/bergwerk/path4/nexus/rueck/1454776724285_rueck.csv"));
//SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "/bergwerk/path4/nexus/vor/1454776525797.csv"));
// live data on the smartphone
if (1 == 1) {
// use android's sensors
SensorFactory::set(new SensorFactoryAndroid());
// write them to file??
//const std::string file = Settings::Data::getRecordsDir() + "/" + std::to_string(Timestamp::fromUnixTime().ms()) + ".csv";
//SensorWriter* writer = new SensorWriter();
//writer->start(file);
// start the sensors
SensorFactory::get().getAccelerometer().start();
SensorFactory::get().getGyroscope().start();
SensorFactory::get().getBarometer().start();
SensorFactory::get().getWiFi().start();
SensorFactory::get().getGPS().start();
SensorFactory::get().getCompass().start();
}
// create the main window
mainWindow = new MainWindow();
//sl = new StepLoggerWrapperAndroid(scaler);
//sl = new StepLoggerWrapper(scaler, mainWindow);
// attach logger
LoggerComposite* log = new LoggerComposite();
log->addLogger(new LoggerCOUT());
log->addLogger(new LoggerAndroid());
log->addLogger(new LoggerUI(mainWindow->getInfoWidget()));
Log::setLogger(log);
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::onLoadButton, this, &Controller::onLoadButton), "connect() failed");
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::onDebugButton, this, &Controller::onDebugButton), "connect() failed");
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::onStartButton, this, &Controller::onStartButton), "connect() failed");
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::onTransparentButton, this, &Controller::onTransparentButton), "connect() failed");
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::onCameraButton, this, &Controller::onCameraButton), "connect() failed");
Assert::isTrue(connect(mainWindow->getMainMenu(), &MainMenu::on3DButton, this, &Controller::on3DButton), "connect() failed");
// order is important! otherwise OpenGL fails!
mainWindow->show();
// // start all sensors
// SensorFactory::get().getAccelerometer().start();
// SensorFactory::get().getGyroscope().start();
// SensorFactory::get().getBarometer().start();
// SensorFactory::get().getWiFi().start();
}
MapView3D* Controller::getMapView3D() const {
return mainWindow->getMapView3D();
}
MapView2D* Controller::getMapView2D() const {
return mainWindow->getMapView2D();
}
MainMenu* Controller::getMainMenu() const {
return mainWindow->getMainMenu();
}
InfoWidget* Controller::getInfoWidget() const {
return mainWindow->getInfoWidget();
}
#include <QMessageBox>
#include <Indoor/sensors/radio/setup/WiFiOptimizer.h>
void buildGridOnce(Grid<MyGridNode>* grid, Floorplan::IndoorMap* map, const std::string& fpFile, const std::string& saveFile) {
//FloorplanHelper::align(map, grid->getGridSize_cm());
// ask questions
const QMessageBox::StandardButton replyWiFiFP = QMessageBox::question(nullptr, "WiFi", "Use Fingerprints for WiFiCalibration?\n\nYes: Use fingerprints and num-optimize AP-Params\nNo: Use APs from the map.xml (pos+params)", QMessageBox::Yes|QMessageBox::No);
// WiFi setup
WiFiModelLogDistCeiling wifiModel(map);
if (replyWiFiFP == QMessageBox::Yes) {
WiFiCalibrationDataModel mdl(fpFile);
Assert::isFalse(mdl.getFingerprints().empty(), "no fingerprints available!");
WiFiOptimizer::LogDistCeiling opt(map, Settings::WiFiModel::vg_calib);
for (const WiFiFingerprint& fp : mdl.getFingerprints()) {
opt.addFingerprint(fp);
}
const WiFiOptimizer::LogDistCeiling::APParamsList res = opt.optimizeAll(opt.NONE);
WiFiGridEstimator::estimate(*grid, wifiModel, Settings::smartphoneAboveGround);
for (const WiFiOptimizer::LogDistCeiling::APParamsMAC& ap : res.get()) {
const WiFiModelLogDistCeiling::APEntry entry(ap.params.getPos(), ap.params.txp, ap.params.exp, ap.params.waf);
wifiModel.addAP(ap.mac, entry);
}
} else {
// NOTE IPIN UAH map does not make sense.. APs look like VAPs but are not
// -> disable VAP-grouping in Settings.h [this is for eval and here]
// load all APs from the floorplan and use same TXP/EXP/WAF for all of them
//wifiModel.loadAPs(map, Settings::WiFiModel::vg_calib, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF);
wifiModel.loadAPs(map, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF);
Assert::isFalse(wifiModel.getAllAPs().empty(), "no AccessPoints stored within the map.xml");
}
// build the grid
GridFactory<MyGridNode> gf(*grid);
gf.build(map);
// add node-importance
Importance::addImportance(*grid);
// stamp WiFi signal-strengths onto the grid
WiFiGridEstimator::estimate(*grid, wifiModel, Settings::smartphoneAboveGround);
// serialize the grid
std::ofstream out(saveFile, std::ofstream::binary);
grid->write(out);
out.close();
}
void buildWiFiModelOnce(WiFiModel* wifiModel, Floorplan::IndoorMap* map, const std::string& fpFile, const std::string& wifiModelFile){
// ask questions
const QMessageBox::StandardButton replyWiFiFP = QMessageBox::question(nullptr, "WiFi", "Use Fingerprints for WiFiCalibration?\n\nYes: Use fingerprints and num-optimize AP-Params\nNo: Use APs from the map.xml (pos+params)", QMessageBox::Yes|QMessageBox::No);
// WiFi setup
wifiModel = new WiFiModelLogDistCeiling(map);
if (replyWiFiFP == QMessageBox::Yes) {
std::ifstream inp(wifiModelFile, std::ifstream::binary);
if (!inp.good() || (inp.peek()&&0) || inp.eof()) {
Log::add("Controller", "Create new WiFiModel");
WiFiCalibrationDataModel mdl(fpFile);
Assert::isFalse(mdl.getFingerprints().empty(), "no fingerprints available!");
WiFiOptimizer::LogDistCeiling opt(map, Settings::WiFiModel::vg_calib);
for (const WiFiFingerprint& fp : mdl.getFingerprints()) {
opt.addFingerprint(fp);
}
const WiFiOptimizer::LogDistCeiling::APParamsList res = opt.optimizeAll(opt.NONE);
for (const WiFiOptimizer::LogDistCeiling::APParamsMAC& ap : res.get()) {
const WiFiModelLogDistCeiling::APEntry entry(ap.params.getPos(), ap.params.txp, ap.params.exp, ap.params.waf);
((WiFiModelLogDistCeiling*)wifiModel)->addAP(ap.mac, entry);
}
wifiModel->saveXML(wifiModelFile);
} else {
Log::add("Controller", "Use existing WifiModel");
// load WiFiModel from file. The factory will create the correct instance
//WiFiModel->loadXML(setup.wifiModel);
WiFiModelFactory fac(map);
wifiModel = fac.loadXML(wifiModelFile);
}
} else {
Log::add("Controller", "Read AP from File");
// load all APs from the floorplan and use same TXP/EXP/WAF for all of them
((WiFiModelLogDistCeiling*)wifiModel)->loadAPs(map, Settings::WiFiModel::TXP, Settings::WiFiModel::EXP, Settings::WiFiModel::WAF);
Assert::isFalse(wifiModel->getAllAPs().empty(), "no AccessPoints stored within the map.xml");
}
}
void Controller::on3DButton() {
static bool use3D = false;
use3D = !use3D;
getMapView2D()->setVisible(!use3D);
getMapView3D()->setVisible( use3D);
}
void Controller::onLoadButton() {
// pick a map to load
QDir dir = LoadSetupDialog::pickSetupFolder();
// cancelled?
if (dir.path() == ".") { return; }
loadNavMesh(dir);
}
void Controller::loadGrid(QDir dir) {
QFile fMap(dir.path() + "/map.xml");
QFile fGrid(dir.path() + "/grid.dat");
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
Assert::isTrue(fMap.exists(), "map.xml missing");
//Assert::isTrue(fGrid.exists(), "grid.dat missing");
fMap.open(QIODevice::ReadOnly);
QString str = QString(fMap.readAll());
im = Floorplan::Reader::readFromString(str.toStdString());
const std::string sGrid = fGrid.fileName().toStdString();
std::ifstream inp(sGrid, std::ifstream::binary);
//Assert::isTrue(inp.good(), "failed to open grid.dat");
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
// create a new, empty grid
if (grid) {delete grid; grid = nullptr;}
grid = new Grid<MyGridNode>(Settings::Grid::gridSize_cm);
// grid.dat empty? -> build one and save it
if (!inp.good() || (inp.peek()&&0) || inp.eof()) {
buildGridOnce(grid, im, sWiFiFP, sGrid);
} else {
grid->read(inp);
}
// create a new navigator
if (nav) {delete nav; nav = nullptr;}
nav = new GridBased::NavControllerGrid(this, im, grid);
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
getMapView3D()->setMap(im);
getMapView2D()->setMap(wifiCalib, im);
getMapView3D()->showGridImportance(grid);
getMapView2D()->showGridImportance(grid);
getMapView3D()->setVisible(false);
// attach ipin step logger
//nav->addListener(sl);
}
void Controller::loadNavMesh(QDir dir) {
QFile fMap(dir.path() + "/map.xml");
QFile fGrid(dir.path() + "/grid.dat");
QFile fWiFiFP(dir.path() + "/wifi_fp.dat");
QFile fWiFiModel(dir.path() + "/wifimodel.dat");
Assert::isTrue(fMap.exists(), "map.xml missing");
fMap.open(QIODevice::ReadOnly);
QString str = QString(fMap.readAll());
im = Floorplan::Reader::readFromString(str.toStdString());
const std::string sWiFiFP = fWiFiFP.fileName().toStdString();
const std::string sWiFiModel = fWiFiModel.fileName().toStdString();
buildWiFiModelOnce(wifiModel, im, sWiFiFP, sWiFiModel);
// create navmesh
if (navMesh) {delete navMesh; navMesh = nullptr;}
NM::NavMeshSettings settings;
NM::NavMeshFactory<NM::NavMeshTriangle> fac(navMesh, settings);
fac.build(im);
// create a new navigator
if (nav) {delete nav; nav = nullptr;}
nav = new MeshBased::NavControllerMesh(this, im, navMesh, wifiModel);
WiFiCalibrationDataModel* wifiCalib = new WiFiCalibrationDataModel(sWiFiFP);
getMapView3D()->setMap(im);
getMapView2D()->setMap(wifiCalib, im);
getMapView3D()->showGridImportance(grid);
getMapView2D()->showGridImportance(grid);
getMapView3D()->setVisible(false);
// attach ipin step logger
//nav->addListener(sl);
}
void Controller::onDebugButton() {
mainWindow->getSensorDataWidget()->setVisible( !mainWindow->getSensorDataWidget()->isVisible() );
}
void Controller::onStartButton() {
nav->start();
}
void Controller::onTransparentButton() {
mainWindow->getMapView3D()->toggleRenderMode();
}
void Controller::onCameraButton() {
nav->toggleCamera();
}