diff options
author | Richard Moe Gustavsen <richard.gustavsen@digia.com> | 2013-05-30 10:07:29 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-06-05 21:15:26 +0200 |
commit | 102bdf35b13f1b60df26052341ebc5a2833518c7 (patch) | |
tree | d603ff2116af12f4d3a64a8a8987107b83e0383e /src/plugins | |
parent | e8237a3d19e90c31af6d5a6c5e3a2f7815740226 (diff) | |
download | qtsensors-102bdf35b13f1b60df26052341ebc5a2833518c7.tar.gz |
iOS: change accelerometer to use QTimer for polling
According to the docs (CMMotionManager class reference) there are
two ways of interacting with the accelerometer; Either through the
callback API (NSOperationQueue), or peridic sampling (polling).
Our first implementation of IOSAcceleometer used the former
technique, which turns out to have bad performance when using the
sensor together with a fine-grained QTimer. And this case is
pretty common when using sensors together with e.g QML.
Reading through the docs more carefully, they recommend using the
polling technique when creating games instead since the
NSOperationQueue introduces some overhead. So this patch does
that, change the implementation to use QTimer based polling. And
this solves the performance issues found.
Change-Id: Ifde0d2292302467afb8db90a954ef45f3238350e
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/sensors/ios/iosaccelerometer.h | 9 | ||||
-rw-r--r-- | src/plugins/sensors/ios/iosaccelerometer.mm | 52 |
2 files changed, 24 insertions, 37 deletions
diff --git a/src/plugins/sensors/ios/iosaccelerometer.h b/src/plugins/sensors/ios/iosaccelerometer.h index 5fcac19..1a6560b 100644 --- a/src/plugins/sensors/ios/iosaccelerometer.h +++ b/src/plugins/sensors/ios/iosaccelerometer.h @@ -42,29 +42,28 @@ #ifndef IOSACCELEROMETER_H #define IOSACCELEROMETER_H -#include <Foundation/Foundation.h> +#include <CoreMotion/CMMotionManager.h> #include <qsensorbackend.h> #include <qaccelerometer.h> QT_BEGIN_NAMESPACE -@class QtIoAccelListener; - class IOSAccelerometer : public QSensorBackend { public: static char const * const id; explicit IOSAccelerometer(QSensor *sensor); - ~IOSAccelerometer(); + void timerEvent(QTimerEvent *); void start(); void stop(); private: - NSOperationQueue *m_updateQueue; + CMMotionManager *m_motionManager; QAccelerometerReading m_reading; + int m_timer; }; QT_END_NAMESPACE diff --git a/src/plugins/sensors/ios/iosaccelerometer.mm b/src/plugins/sensors/ios/iosaccelerometer.mm index b657b50..5f9c0f1 100644 --- a/src/plugins/sensors/ios/iosaccelerometer.mm +++ b/src/plugins/sensors/ios/iosaccelerometer.mm @@ -40,8 +40,6 @@ ****************************************************************************/ #include <UIKit/UIAccelerometer.h> -#include <CoreMotion/CMMotionManager.h> -#include <QPointer> #include "iosaccelerometer.h" #include "iosmotionmanager.h" @@ -52,49 +50,39 @@ QT_BEGIN_NAMESPACE IOSAccelerometer::IOSAccelerometer(QSensor *sensor) : QSensorBackend(sensor) - , m_updateQueue([[NSOperationQueue alloc] init]) + , m_motionManager([QIOSMotionManager sharedManager]) + , m_timer(0) { setReading<QAccelerometerReading>(&m_reading); addDataRate(1, 100); // 100Hz addOutputRange(-22.418, 22.418, 0.17651); // 2G } -IOSAccelerometer::~IOSAccelerometer() -{ - [m_updateQueue release]; -} - void IOSAccelerometer::start() { - CMMotionManager *motionManager = [QIOSMotionManager sharedManager]; - // Convert from Hz to NSTimeInterval: int hz = sensor()->dataRate(); - motionManager.accelerometerUpdateInterval = (hz == 0) ? 0 : 1. / hz; - - QPointer<QObject> self = this; - [motionManager startAccelerometerUpdatesToQueue:m_updateQueue withHandler:^(CMAccelerometerData *data, NSError *error) { - // NSOperationQueue is multi-threaded, so we process the data by queuing a callback to - // the main application queue. By the time the callback executes, IOSAccelerometer might - // have been deleted, so we need an extra QPointer check for that: - dispatch_async(dispatch_get_main_queue(), ^{ - if (self) { - Q_UNUSED(error); - // Convert from NSTimeInterval to microseconds and G to m/s2, and flip axes: - CMAcceleration acc = data.acceleration; - const qreal G = 9.8066; - m_reading.setTimestamp(quint64(data.timestamp * 1000000)); - m_reading.setX(qreal(acc.x) * G * -1); - m_reading.setY(qreal(acc.y) * G * -1); - m_reading.setZ(qreal(acc.z) * G * -1); - newReadingAvailable(); - } - }); - }]; + m_timer = startTimer(1000 / (hz == 0 ? 60 : hz)); + [m_motionManager startAccelerometerUpdates]; } void IOSAccelerometer::stop() { - [[QIOSMotionManager sharedManager] stopAccelerometerUpdates]; + [m_motionManager stopAccelerometerUpdates]; + killTimer(m_timer); + m_timer = 0; +} + +void IOSAccelerometer::timerEvent(QTimerEvent *) +{ + // Convert from NSTimeInterval to microseconds and G to m/s2, and flip axes: + CMAccelerometerData *data = m_motionManager.accelerometerData; + CMAcceleration acc = data.acceleration; + static const qreal G = 9.8066; + m_reading.setTimestamp(quint64(data.timestamp * 1e6)); + m_reading.setX(qreal(acc.x) * G * -1); + m_reading.setY(qreal(acc.y) * G * -1); + m_reading.setZ(qreal(acc.z) * G * -1); + newReadingAvailable(); } QT_END_NAMESPACE |