performance enhancements

memory enhancements
prevent starting sensors more than once
fix for wifi lag issues
map scaling for huge buildings
This commit is contained in:
2016-10-01 10:21:15 +02:00
parent 833327bafd
commit 44f9b6ac80
16 changed files with 197 additions and 26 deletions

View File

@@ -51,9 +51,9 @@ Controller::Controller() : sl(scaler) {
//SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "bergwerk/path3/nexus/vor/1454782562231.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/rueck/1454776724285_rueck.csv"));
SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "/bergwerk/path4/nexus/vor/1454776525797.csv")); //SensorFactory::set(new SensorFactoryOffline(Settings::Data::getOfflineDir() + "/bergwerk/path4/nexus/vor/1454776525797.csv"));
//SensorFactory::set(new SensorFactoryAndroid()); SensorFactory::set(new SensorFactoryAndroid());
// SensorFactory::get().getAccelerometer().start(); // SensorFactory::get().getAccelerometer().start();
// SensorFactory::get().getGyroscope().start(); // SensorFactory::get().getGyroscope().start();
// SensorFactory::get().getBarometer().start(); // SensorFactory::get().getBarometer().start();
@@ -218,8 +218,6 @@ void Controller::onLoadButton() {
getMapView3D()->showGridImportance(grid); getMapView3D()->showGridImportance(grid);
getMapView2D()->showGridImportance(grid); getMapView2D()->showGridImportance(grid);
getMapView3D()->setVisible(false);
// attach ipin step logger // attach ipin step logger
nav->addListener(&sl); nav->addListener(&sl);

View File

@@ -42,7 +42,8 @@ namespace Settings {
namespace MapView { namespace MapView3D {
const int maxColorPoints = 10000;
constexpr int fps = 15; constexpr int fps = 15;
const Timestamp msPerFrame = Timestamp::fromMS(1000/fps); const Timestamp msPerFrame = Timestamp::fromMS(1000/fps);
} }

View File

@@ -18,7 +18,8 @@ public class WiFi {
private static WifiManager manager; private static WifiManager manager;
private static BroadcastReceiver receiver; private static BroadcastReceiver receiver;
private static Thread tHeartbeat = null;
private static long lastScanStartTS = 0;
/** called when a scan is completed successfully */ /** called when a scan is completed successfully */
public static native void onScanComplete(final byte[] result); public static native void onScanComplete(final byte[] result);
@@ -48,7 +49,28 @@ public class WiFi {
act.registerReceiver(WiFi.receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); act.registerReceiver(WiFi.receiver, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
// start the first scan // start the first scan
triggerOneScan(); triggerOneScan();
// if the scan result takes longer than X milliseconds,
// trigger another-scan to ensure nothing is stuck
final Runnable r = new Runnable() {
public void run() {
while(true) {
final long ts = System.currentTimeMillis();
final long diff = ts - lastScanStartTS;
if (diff > 1000) { triggerOneScan(); }
try {Thread.sleep(200);} catch (final Exception e) {;}
}
}
};
// start the heartbeat once
if (tHeartbeat == null) {
tHeartbeat = new Thread(r);
tHeartbeat.start();
}
return 1337; return 1337;
@@ -91,6 +113,7 @@ public class WiFi {
try { try {
if(!manager.startScan()) {throw new RuntimeException("Cant start WiFi!");} if(!manager.startScan()) {throw new RuntimeException("Cant start WiFi!");}
lastScanStartTS = System.currentTimeMillis();
}catch (final Exception e) { }catch (final Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@@ -5,7 +5,7 @@
#include "../nav/NavControllerListener.h" #include "../nav/NavControllerListener.h"
#include <Indoor/misc/Debug.h> #include <Indoor/misc/Debug.h>
#ifdef Android #ifdef ANDROID
#include <QtAndroidExtras> #include <QtAndroidExtras>
#endif #endif
@@ -48,10 +48,10 @@ private:
/** call java */ /** call java */
void log(const double x, const double y, const double z) { void log(const double x, const double y, const double z) {
#ifdef Android #ifdef ANDROID
Log::add("SLWA", "calling android with lon/lat/floor"); //Log::add("SLWA", "calling android with lon/lat/floor");
int res = QAndroidJniObject::callStaticMethod<int>("indoor/java/StepLoggerClient", "log", "(DDD)I", x, y, z); int res = QAndroidJniObject::callStaticMethod<int>("indoor/java/StepLoggerClient", "log", "(DDD)I", x, y, z);
if (res != 1337) {throw Exception("error while logging");} //if (res != 1337) {throw Exception("invalid return code while sending the current position to StepLogger.\nService Down?");}
#endif #endif
} }

View File

@@ -336,7 +336,7 @@ private:
} }
const int display_ms = Settings::MapView::msPerFrame.ms(); const int display_ms = Settings::MapView3D::msPerFrame.ms();
/** UI update loop */ /** UI update loop */
void updateMapViewLoop() { void updateMapViewLoop() {

View File

@@ -23,6 +23,8 @@ private:
; ;
} }
bool started = false;
public: public:
/** singleton access */ /** singleton access */
@@ -33,26 +35,30 @@ public:
void start() override { void start() override {
if (started) {return;}
started = true;
auto onSensorData = [&] () { auto onSensorData = [&] () {
AccelerometerData data(acc.reading()->x(), acc.reading()->y(), acc.reading()->z()); AccelerometerData data(acc.reading()->x(), acc.reading()->y(), acc.reading()->z());
informListeners(data); informListeners(data);
}; };
// accelerometer is usually verry fast -> limit the maximum data-rate to 200 Hz (5ms)
acc.setDataRate(200);
acc.connect(&acc, &QAccelerometer::readingChanged, onSensorData); acc.connect(&acc, &QAccelerometer::readingChanged, onSensorData);
acc.start(); acc.start();
} }
bool isRunning() const override { bool isRunning() const override {
return acc.isActive(); return started;
} }
void stop() override { void stop() override {
throw "TODO"; throw "TODO";
} }
}; };
#endif // ANDROID #endif // ANDROID

View File

@@ -22,6 +22,8 @@ private:
; ;
} }
bool started = false;
public: public:
/** singleton access */ /** singleton access */
@@ -32,6 +34,9 @@ public:
void start() override { void start() override {
if (started) {return;}
started = true;
auto onSensorData = [&] () { auto onSensorData = [&] () {
BarometerData data(baro.reading()->pressure() / 100.0f); // convert Pa to hPa BarometerData data(baro.reading()->pressure() / 100.0f); // convert Pa to hPa
informListeners(data); informListeners(data);
@@ -43,7 +48,7 @@ public:
} }
bool isRunning() const override { bool isRunning() const override {
return baro.isActive(); return started;
} }
void stop() override { void stop() override {

View File

@@ -22,6 +22,8 @@ private:
; ;
} }
bool started = false;
public: public:
/** singleton access */ /** singleton access */
@@ -36,18 +38,26 @@ public:
void start() override { void start() override {
if (started) {return;}
started = true;
auto onSensorData = [&] () { auto onSensorData = [&] () {
GyroscopeData data(degToRad(gyro.reading()->x()), degToRad(gyro.reading()->y()), degToRad(gyro.reading()->z())); GyroscopeData data(degToRad(gyro.reading()->x()), degToRad(gyro.reading()->y()), degToRad(gyro.reading()->z()));
informListeners(data); informListeners(data);
// const Timestamp now = Timestamp::fromRunningTime();
// Log::add("123", "ts:" + std::to_string(now.ms()));
}; };
// gyroscope is usually not as fast as the acceleromter -> limiting not needed
//gyro.setDataRate(200);
gyro.connect(&gyro, &QGyroscope::readingChanged, onSensorData); gyro.connect(&gyro, &QGyroscope::readingChanged, onSensorData);
gyro.start(); gyro.start();
} }
bool isRunning() const override { bool isRunning() const override {
return gyro.isActive(); return started;
} }
void stop() override { void stop() override {

View File

@@ -9,6 +9,8 @@
#include "../../misc/Debug.h" #include "../../misc/Debug.h"
#include "../WiFiSensor.h" #include "../WiFiSensor.h"
#include <Indoor/misc/Debug.h>
class WiFiSensorAndroid : public WiFiSensor { class WiFiSensorAndroid : public WiFiSensor {
private: private:
@@ -30,11 +32,11 @@ public:
// do NOT start twice! // do NOT start twice!
if (started) {return;} if (started) {return;}
started = true;
// start scanning // start scanning
int res = QAndroidJniObject::callStaticMethod<int>("indoor/java/WiFi", "start", "()I"); int res = QAndroidJniObject::callStaticMethod<int>("indoor/java/WiFi", "start", "()I");
if (res != 1337) {throw Exception("error while starting WiFi");} if (res != 1337) {throw Exception("error while starting WiFi");}
started = true;
} }
@@ -46,7 +48,11 @@ public:
return started; return started;
} }
/** called from java. handle the given incoming scan result */ /**
* called from WiFi.java
* handle the given incoming scan result
* just a bit curious, thus std::string instead of std::string&
*/
void handle(const std::string data) { void handle(const std::string data) {
// to-be-constructed sensor data // to-be-constructed sensor data
@@ -68,6 +74,16 @@ public:
// call listeners // call listeners
informListeners(sensorData); informListeners(sensorData);
// interval debug
// static Timestamp lastTS;
// const Timestamp diff = curTS - lastTS;
// Log::add("wifi", std::to_string(diff.ms()));
// if (diff.ms() > 650) {
// Log::add("wifi", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
// }
// lastTS = curTS;
} }
}; };

View File

@@ -22,14 +22,20 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
mainMenu = new MainMenu(this); mainMenu = new MainMenu(this);
infoWidget = new InfoWidget(this); infoWidget = new InfoWidget(this);
sensorWidget = new SensorDataWidget(this); sensorWidget->setVisible(false); sensorWidget = new SensorDataWidget(this);
//sensorWidget->setVisible(false); // ensure we are fullscreen
showMaximized(); showMaximized();
sleep(1); sleep(1);
emit resizeEvent(nullptr); emit resizeEvent(nullptr);
// important! must be called AFTER window is visible
// otherwise MapView3D's openGL context is uninitialized.
sensorWidget->setVisible(false);
mapView2D->setVisible(true);
mapView3D->setVisible(false);
} }
void MainWindow::resizeEvent(QResizeEvent* event) { void MainWindow::resizeEvent(QResizeEvent* event) {

View File

@@ -4,8 +4,10 @@
#include <QResizeEvent> #include <QResizeEvent>
#include <QSlider> #include <QSlider>
#include <QGridLayout> #include <QGridLayout>
#include <QGestureEvent>
#include <Indoor/floorplan/v2/Floorplan.h> #include <Indoor/floorplan/v2/Floorplan.h>
#include <Indoor/floorplan/v2/FloorplanHelper.h>
#include "Floor2D.h" #include "Floor2D.h"
#include "ColorPoints2D.h" #include "ColorPoints2D.h"
@@ -67,7 +69,12 @@ MapView2D::MapView2D(QWidget *parent) : QWidget(parent) {
lay->addWidget(btnLayerPlus, row, 2, 1, 1); lay->addWidget(btnLayerPlus, row, 2, 1, 1);
// start with invisible particles. speeds things up a bit
colorPoints->setVisible(false);
// we want to receive pinch gestures
//setAttribute(Qt::WA_AcceptTouchEvents, true);
grabGesture(Qt::PinchGesture);
} }
@@ -96,7 +103,11 @@ void MapView2D::setMap(WiFiCalibrationDataModel* mdl, Floorplan::IndoorMap* map)
wifiCalib = new WiFiCalibTool(mdl, map); wifiCalib = new WiFiCalibTool(mdl, map);
elementsB.push_back(wifiCalib); elementsB.push_back(wifiCalib);
scaler.setCenterM(Point2(70, 35)); const BBox3 bbox3 = FloorplanHelper::getBBox(map);
const BBox2 bbox2 = BBox2(bbox3.getMin().xy(), bbox3.getMax().xy());
scaler.setMapBBox(bbox2);
scaler.setCenterM(Point2(bbox2.getCenter().x, bbox2.getCenter().y));
} }
@@ -169,6 +180,16 @@ void MapView2D::mouseReleaseEvent(QMouseEvent* evt) {
} }
void MapView2D::wheelEvent(QWheelEvent* event) {
if (event->delta() < 0) {
scaler.mulScale(0.5);
emit update();
} else {
scaler.mulScale(2.0);
emit update();
}
}
void MapView2D::paintEvent(QPaintEvent*) { void MapView2D::paintEvent(QPaintEvent*) {
QPainter qp(this); QPainter qp(this);
@@ -183,3 +204,42 @@ void MapView2D::paintEvent(QPaintEvent*) {
qp.end(); qp.end();
} }
bool MapView2D::event(QEvent *event) {
switch (event->type()) {
case QEvent::Gesture:
return gestureEvent(static_cast<QGestureEvent*>(event));
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
// prevent [additional] mouse events for undetected gestures [more than 1 finger]
// TODO: not yet stable... improvements?
if (static_cast<QTouchEvent*>(event)->touchPoints().count() == 2) {return true;}
break;
default:
break;
}
// event not consumed. bubble it to following stages.
// this will e.g. generate mouseMoveEvent etc.
return QWidget::event(event);
}
bool MapView2D::gestureEvent(QGestureEvent *event) {
if (QGesture* pinch = event->gesture(Qt::PinchGesture)) {
const QPinchGesture* pg = static_cast<QPinchGesture *>(pinch);
scaler.mulScale(pg->scaleFactor());
emit update();
return true; // event consumed
}
// event not consumed
return false;
}

View File

@@ -21,6 +21,7 @@ class MyGridNode;
class Renderable2D; class Renderable2D;
class QSlider; class QSlider;
class QPushButton; class QPushButton;
class QGestureEvent;
class ColorPoints2D; class ColorPoints2D;
class Path2D; class Path2D;
@@ -127,6 +128,10 @@ public slots:
void mousePressEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*); void mouseMoveEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*); void mouseReleaseEvent(QMouseEvent*);
void wheelEvent(QWheelEvent*);
bool event(QEvent*);
bool gestureEvent(QGestureEvent *event);
}; };

View File

@@ -3,6 +3,7 @@
#include <QPoint> #include <QPoint>
#include <Indoor/geo/Point2.h> #include <Indoor/geo/Point2.h>
#include <Indoor/geo/BBox2.h>
class Scaler2D { class Scaler2D {
@@ -13,6 +14,8 @@ private:
float rotation_rad = 0.0f; float rotation_rad = 0.0f;
float scaleFactor = 1; float scaleFactor = 1;
BBox2 mapBBox_m;
public: public:
Scaler2D() { Scaler2D() {
@@ -32,11 +35,17 @@ public:
/** change the point displayed within the center of the screen */ /** change the point displayed within the center of the screen */
void setCenterM(const Point2 center_m) { void setCenterM(const Point2 center_m) {
this->center_m = center_m; this->center_m = center_m;
if (!mapBBox_m.isInvalid()) {
if (this->center_m.x < mapBBox_m.getMin().x) {this->center_m.x = mapBBox_m.getMin().x;}
if (this->center_m.y < mapBBox_m.getMin().y) {this->center_m.y = mapBBox_m.getMin().y;}
if (this->center_m.x > mapBBox_m.getMax().x) {this->center_m.x = mapBBox_m.getMax().x;}
if (this->center_m.y > mapBBox_m.getMax().y) {this->center_m.y = mapBBox_m.getMax().y;}
}
} }
/** change the point displayed within the center of the screen */ /** change the point displayed within the center of the screen */
void setCenterPX(const Point2 center_px) { void setCenterPX(const Point2 center_px) {
this->center_m = pxToM(center_px); setCenterM(pxToM(center_px));
} }
Point2 getCenterPX() const { Point2 getCenterPX() const {
@@ -48,10 +57,21 @@ public:
this->rotation_rad = rad; this->rotation_rad = rad;
} }
/** set the map's scaling */
void setScale(const float scale) { void setScale(const float scale) {
this->scaleFactor = scale; this->scaleFactor = scale;
if (this->scaleFactor < 0.1) {this->scaleFactor = 0.1;}
if (this->scaleFactor > 4.0) {this->scaleFactor = 4.0;}
} }
void mulScale(const float mod) {
setScale(this->scaleFactor * mod);
}
/** set the map's bbox. used to prevent from scrolling outside of the map */
void setMapBBox(const BBox2 bbox_m) {
this->mapBBox_m = bbox_m;
}
public: public:

View File

@@ -108,14 +108,26 @@ void MapView3D::initializeGL() {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
// start background update timer
timer.start(Settings::MapView::msPerFrame.ms(), this);
// OpenGL is now initialized // OpenGL is now initialized
isGLInitialized = true; isGLInitialized = true;
} }
void MapView3D::setVisible(bool visible) {
// inform parent
QOpenGLWidget::setVisible(visible);
if (!visible) {
// stop background update timer
timer.stop();
} else {
// start background update timer
timer.start(Settings::MapView3D::msPerFrame.ms(), this);
}
}
void MapView3D::paintGL() { void MapView3D::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw(); draw();

View File

@@ -140,6 +140,8 @@ public:
void toggleRenderMode(); void toggleRenderMode();
void setVisible(bool visible) override;
public slots: public slots:
void mousePressEvent(QMouseEvent*); void mousePressEvent(QMouseEvent*);

View File

@@ -10,6 +10,7 @@
//#include "../gl/GLTriangles.h" //#include "../gl/GLTriangles.h"
#include "../Renderable.h" #include "../Renderable.h"
#include "../../../../Settings.h"
#include "../../../../nav/Node.h" #include "../../../../nav/Node.h"
class ColorPoints : public Renderable { class ColorPoints : public Renderable {
@@ -31,6 +32,9 @@ public:
points.clear(); points.clear();
// do not display?
if (grid->getNumNodes() > Settings::MapView3D::maxColorPoints) {return;}
float min = +INFINITY; float min = +INFINITY;
float max = -INFINITY; float max = -INFINITY;
@@ -62,6 +66,9 @@ public:
points.clear(); points.clear();
// do not display?
if (particles.size() > Settings::MapView3D::maxColorPoints) {return;}
// group particles by grid-point // group particles by grid-point
std::unordered_map<GridPoint, float> weights; std::unordered_map<GridPoint, float> weights;
for (const K::Particle<T>& p : particles) { for (const K::Particle<T>& p : particles) {