examples/sensors/test_manual/test_manual.cpp
changeset 0 876b1a06bc25
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/sensors/test_manual/test_manual.cpp	Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,796 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QObject>
+#include <QTest>
+#include <QDebug>
+#include <QSettings>
+#include <iostream>
+
+
+#include <qsensor.h>
+#include <qorientationsensor.h>
+#include <qaccelerometer.h>
+#include <qrotationsensor.h>
+#include <qmagnetometer.h>
+#include <qcompass.h>
+#include "sensorslotclass.h"
+
+QTM_USE_NAMESPACE
+
+        static QOrientationReading::Orientation o2;
+static QOrientationSensor orientationSensor;
+static QAccelerometer accelerometer;
+static QRotationSensor rotationSensor;
+static QAccelerometerReading* acceReading;
+static QRotationReading* rotReading;
+static QMagnetometer magnetometer;
+static QMagnetometerReading* maggeReading;
+static QCompass compass;
+static QCompassReading* compassReading;
+
+
+static QString dataRateString;
+static QString dataRangeString;
+static QString resolutionString;
+static int counter;
+static bool isStationary = false;
+
+///////////////////////////////////////////
+//cpp file
+///////////////////////////////////////////
+
+
+SensorSlotClass::SensorSlotClass()
+{
+    int rateMax =0;
+    connect(&orientationSensor, SIGNAL(readingChanged()), this, SLOT(slotOrientationData()));
+    if (orientationSensor.availableDataRates().size()>0){
+        rateMax = orientationSensor.availableDataRates().at(0).second;
+        orientationSensor.setDataRate(rateMax);
+    }
+    orientationSensor.start();
+    connect(&accelerometer, SIGNAL(readingChanged()), this, SLOT(slotAccelerationData()));
+    if (accelerometer.availableDataRates().size()>0){
+        rateMax = accelerometer.availableDataRates().at(0).second;
+        accelerometer.setDataRate(rateMax);
+    }
+    accelerometer.start();
+    connect(&rotationSensor, SIGNAL(readingChanged()), this, SLOT(slotRotationData()));
+    if (rotationSensor.availableDataRates().size()>0){
+        rateMax = rotationSensor.availableDataRates().at(0).second;
+        rotationSensor.setDataRate(rateMax);
+    }
+    rotationSensor.start();
+    magnetometer.setProperty("returnGeoValues", true);
+    connect(&magnetometer, SIGNAL(readingChanged()), this, SLOT(slotMagnetometerData()));
+    if (magnetometer.availableDataRates().size()>0){
+        rateMax = magnetometer.availableDataRates().at(0).second;
+        magnetometer.setDataRate(rateMax);
+    }
+    magnetometer.start();
+
+    connect(&compass, SIGNAL(readingChanged()), this, SLOT(slotCompassData()));
+    if (compass.availableDataRates().size()>0){
+        rateMax = compass.availableDataRates().at(0).second;
+        compass.setDataRate(rateMax);
+    }
+    compass.start();
+
+    m_x=0; m_y=0; m_z=0;
+}
+
+SensorSlotClass::~SensorSlotClass(){
+    disconnect(&compass);
+    compass.stop();
+
+    disconnect(&orientationSensor);
+    orientationSensor.stop();
+
+    disconnect(&rotationSensor);
+    rotationSensor.stop();
+
+    disconnect(&magnetometer);
+    magnetometer.stop();
+
+    disconnect(&accelerometer);
+    accelerometer.stop();
+
+}
+
+
+void SensorSlotClass::slotOrientationData(){
+    o2 = orientationSensor.reading()->orientation();
+    checkRange(&orientationSensor, o2);
+    checkRate(&orientationSensor, m_orientationTimestamp);
+}
+
+
+void SensorSlotClass::slotAccelerationData(){
+
+    acceReading = accelerometer.reading();
+    checkRange(&accelerometer, acceReading->x());
+    checkRange(&accelerometer, acceReading->y());
+    checkRange(&accelerometer, acceReading->z());
+
+    checkRate(&accelerometer, m_accelerometerTimestamp);
+
+    if (isStationary) checkResolution(&accelerometer, acceReading);
+
+}
+
+void SensorSlotClass::slotRotationData(){
+    rotReading = rotationSensor.reading();
+    checkRange(&rotationSensor, rotReading->x());
+    checkRange(&rotationSensor, rotReading->y());
+    checkRange(&rotationSensor, rotReading->z());
+
+    checkRate(&rotationSensor, m_rotationTimestamp);
+}
+
+void SensorSlotClass::slotMagnetometerData(){
+
+    maggeReading = magnetometer.reading();
+    checkRange(&magnetometer, maggeReading->x());
+    checkRange(&magnetometer, maggeReading->y());
+    checkRange(&magnetometer, maggeReading->z());
+
+    checkRate(&magnetometer, m_magnetometerTimestamp);
+
+}
+
+void SensorSlotClass::slotCompassData(){
+    compassReading = compass.reading();
+    checkRange(&compass, (qreal)compassReading->azimuth());
+
+    checkRate(&compass, m_compassTimestamp);
+}
+
+
+void SensorSlotClass::checkRange(QSensor* sensor, qreal value){
+    qreal min = sensor->outputRanges().at(sensor->outputRange()).minimum;
+    qreal max = sensor->outputRanges().at(sensor->outputRange()).maximum;
+
+    if (min>value || value> max){
+        QString num;
+        dataRangeString.append(sensor->type());
+        dataRangeString.append(": range=[");
+        dataRangeString.append(num.setNum(min));
+        dataRangeString.append(",");
+        dataRangeString.append(num.setNum(max));
+        dataRangeString.append("], value =");
+        dataRangeString.append(num.setNum(value));
+        dataRangeString.append("\n");
+    }
+
+}
+
+
+void SensorSlotClass::checkRate(QSensor* sensor, int &exTimestamp){
+    int timestamp = sensor->reading()->timestamp();
+    int diff = timestamp - exTimestamp;
+    int rate = sensor->dataRate();
+    if (rate==0) return;
+    if (diff < (1000/rate)*0.9){
+        dataRateString.append(sensor->type());
+        dataRateString.append(": rate=");
+        dataRateString.append(sensor->dataRate());
+        dataRateString.append(", measured rate=");
+        dataRateString.append(1000/diff);
+        dataRateString.append("\n");
+    }
+
+    exTimestamp = timestamp;
+}
+
+
+void SensorSlotClass::checkResolution(QSensor* sensor, QAccelerometerReading* reading){
+    qreal x = reading->x();
+    qreal y = reading->y();
+    qreal z = reading->z();
+
+
+    qreal resolution = sensor->outputRanges().at(sensor->outputRange()).accuracy;
+
+    if (m_x!=0){
+        qreal diff = qAbs(x-m_x);
+        checkDiff(diff, resolution, ": x resolution=");
+        diff = qAbs(y-m_y);
+        checkDiff(diff, resolution, ": y resolution=");
+        diff = qAbs(z-m_z);
+        checkDiff(diff, resolution, ": z resolution=");
+    }
+    m_x = x;
+    m_y = y;
+    m_z = z;
+
+}
+
+void SensorSlotClass::checkDiff(qreal diff, qreal resolution, QString msg){
+    if (diff==0) return;
+    qreal resolutionMax = 3*resolution;
+
+
+    if (qAbs(diff)<resolution || qAbs(diff)>resolutionMax){
+        QString num;
+        resolutionString.append("\n");
+        resolutionString.append("accelerometer:");
+        resolutionString.append(msg);
+        num.setNum(resolution);
+        resolutionString.append(num);
+        resolutionString.append("!=");
+        num.setNum(qAbs(diff));
+        resolutionString.append(num);
+    }
+
+}
+
+
+
+namespace tests{
+
+    static QOrientationReading::Orientation orientation[] = {
+        QOrientationReading::TopUp,
+        QOrientationReading::TopDown,
+        QOrientationReading::LeftUp,
+        QOrientationReading::RightUp,
+        QOrientationReading::FaceUp,
+        QOrientationReading::FaceDown
+    };
+
+
+    static const float GRAVITY_EARTH = 9.80665;
+    static const float THRESHOLD = GRAVITY_EARTH/4;
+
+    static void pressAnyKey()
+    {
+        std::string value;
+        qDebug()<< "Press any key: \n";
+        std::getline(std::cin, value);
+    }
+
+
+    static QString debugMessage(QString title, qreal expected, qreal measured, qreal threshold){
+        QString msg;
+        msg.append(title);
+        QString num;
+        num.setNum(measured);
+        msg.append(num);
+        msg.append(" was not in range [");
+        num.setNum(expected - threshold);
+        msg.append(num);
+        msg.append(",");
+        num.setNum(expected + threshold);
+        msg.append(num);
+        msg.append("]");
+        msg.append("\n");
+        return msg;
+    }
+
+
+    static void drawDevice(QOrientationReading::Orientation orientation){
+        switch (orientation) {
+        case QOrientationReading::TopUp:
+            std::cout<<"    ___________\n";
+            std::cout<<"    | _______ |\n";
+            std::cout<<"    | |     | |\n";
+            std::cout<<"    | |     | |\n";
+            std::cout<<"    | |_____| |\n";
+            std::cout<<"    | _______ |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    |_________|\n";
+            std::cout<< "Top up \n"; break;
+            break;
+        case QOrientationReading::TopDown:
+            std::cout<<"     _________ \n";
+            std::cout<<"    | _______ |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    | |_|_|_| |\n";
+            std::cout<<"    | _______ |\n";
+            std::cout<<"    | |     | |\n";
+            std::cout<<"    | |     | |\n";
+            std::cout<<"    | |_____| |\n";
+            std::cout<<"    |_________|\n";
+            std::cout<<"Top down \n"; break;
+        case QOrientationReading::LeftUp:
+            std::cout<<"     _________________\n";
+            std::cout<<"    | _______ ______  |\n";
+            std::cout<<"    | |_|_|_| |     | |\n";
+            std::cout<<"    | |_|_|_| |     | |\n";
+            std::cout<<"    | |_|_|_| |_____| |\n";
+            std::cout<<"    |_________________|\n";
+            std::cout<<"Left up  \n"; break;
+        case QOrientationReading::RightUp:
+            std::cout<<"     _________________\n";
+            std::cout<<"    | _______ ______  |\n";
+            std::cout<<"    | |     | |_|_|_| |\n";
+            std::cout<<"    | |     | |_|_|_| |\n";
+            std::cout<<"    | |_____| |_|_|_| |\n";
+            std::cout<<"    |_________________|\n";
+            std::cout<<"Right up \n"; break;
+        case QOrientationReading::FaceUp:
+            std::cout<<"     _________\n";
+            std::cout<<"    |  ' ' '  |\n";
+            std::cout<<"    |_________|\n";
+            std::cout<<"Face up  \n"; break;
+        case QOrientationReading::FaceDown:
+            std::cout<<"     _________\n";
+            std::cout<<"    |         |\n";
+            std::cout<<"    |__._._.__|\n";
+            std::cout<<"Face down\n"; break;
+        case QOrientationReading::Undefined: std::cout<<"Undefined\n"; break;
+        default: std::cout<<"Invalid enum value\n";
+        }
+    }
+
+
+    static const char* orientationAsString(QOrientationReading::Orientation orientation){
+        switch (orientation) {
+        case QOrientationReading::TopUp:     return "Top up   ";
+        case QOrientationReading::TopDown:   return "Top down ";
+        case QOrientationReading::LeftUp:    return  "Left up  ";
+        case QOrientationReading::RightUp:   return "Right up ";
+        case QOrientationReading::FaceUp:    return "Face up  ";
+        case QOrientationReading::FaceDown:  return "Face down";
+        case QOrientationReading::Undefined: return "Undefined";
+        default: return "Invalid enum value";
+        }
+    }
+
+
+    static qreal acce_array[6][3]=
+    {
+        {0, tests::GRAVITY_EARTH, 0},
+        {0, -tests::GRAVITY_EARTH, 0},
+        {-tests::GRAVITY_EARTH, 0, 0},
+        {tests::GRAVITY_EARTH, 0, 0},
+        {0, 0, tests::GRAVITY_EARTH},
+        {0, 0, -tests::GRAVITY_EARTH}};
+
+
+    static qreal rot_array[6][2]=
+    {
+        {90,0},
+        {-90, 0},
+        {0,90},
+        {0,-90},
+        {0, 0},
+        {0, 180}};
+
+    static const qreal ROT_THRESHOLD = 20;
+
+
+    static bool confirm()
+    {
+        std::string value;
+        while (true){
+            qDebug()<< "Answer(y/N):";
+            std::getline(std::cin, value);
+            if (value.compare("Y")==0 || value.compare("y")==0 ) return true;
+            if (value.compare("N")==0 || value.compare("n")==0 || value.compare("")==0 || value.compare(" ")==0 || value.compare("\n")==0) return false;
+        }
+    }
+
+    static bool testMagge(qreal val1, qreal val2, qreal threshold, QString &msg){
+        bool isOk = true;
+
+        if (val1+val2>threshold){
+            isOk = false;
+            QString num;
+            msg.append(num.setNum(val1));
+            msg.append("!=");
+            msg.append(num.setNum(val2));
+            msg.append("\n");
+        }
+        return isOk;
+    }
+
+
+
+    static bool testMagge2(qreal valBig, qreal valSmall1, qreal valSmall2, QString &msg){
+        bool isOk = true;
+        if (qAbs(valBig)< qAbs(valSmall1) || qAbs(valBig)< qAbs(valSmall2)){
+            isOk = false;
+            QString num;
+            msg.append(num.setNum(valBig));
+            msg.append(",");
+            msg.append(num.setNum(valSmall1));
+            msg.append(",");
+            msg.append(num.setNum(valSmall2));
+            msg.append("\n");
+        }
+        return isOk;
+    }
+
+
+    static bool testCompass(qreal val1, qreal val2, QString &msg){
+        bool isOk = true;
+        int threshold = 30;
+
+
+        if (qAbs(val1 - val2)> threshold){
+            if (val1>360-threshold)
+                if ((360 - val1 + val2)< threshold) return isOk;
+            if (val2>360-threshold)
+                if ((360 - val2 + val1)< threshold) return isOk;
+            isOk = false;
+            msg.append("Compass failure:");
+            QString num;
+            msg.append(num.setNum(val1));
+            msg.append("!=");
+            msg.append(num.setNum(val2));
+            msg.append("\n");
+        }
+        return isOk;
+    }
+
+
+    static bool testRot(qreal azimuth, qreal rotZ, QString &msg){
+        bool isOk = true;
+
+
+        qreal tmpAzimuth = rotZ>0 ? 360 -rotZ : -rotZ;
+        int threshold = 30;
+
+
+        if (qAbs(azimuth - tmpAzimuth)> threshold){
+            if (tmpAzimuth> 360-threshold)
+                if ((360 - tmpAzimuth + azimuth)< threshold) return isOk;
+            if (azimuth> 360-threshold)
+                if ((360 - azimuth + tmpAzimuth)< threshold) return isOk;
+
+            isOk=false;
+            msg.append("Rot/compass comparison failed: ");
+            QString num;
+            msg.append(num.setNum(azimuth));
+            msg.append("!=");
+            msg.append(num.setNum(tmpAzimuth));
+            msg.append("\n");
+        }
+
+        return isOk;
+    }
+
+
+
+}
+
+
+class test_manual: public QObject{
+    Q_OBJECT
+    private slots:
+    void testOrientation();
+    void testDataRate();
+    void testOutputRange();
+    void testResolution();
+};
+
+
+void test_manual::testOrientation()
+
+{
+
+    SensorSlotClass slotClass;
+
+    bool hasZ = rotationSensor.property("hasZ").toBool();
+
+    int j=0,k=0,l=0;
+
+
+    qreal magge_x[6];
+    qreal magge_y[6];
+    qreal magge_z[6];
+    qreal rot_x[6];
+    qreal rot_y[6];
+    qreal rot_z[6];
+    qreal compass_azimuth[6];
+    qreal compass_level[6];
+
+    QString tmp("\n");
+
+
+    for (; counter<7; counter++){
+        qDebug()<<"Put the device in following position, try to preserve compass direction:\n";
+        if (counter==4) qDebug()<<"Put the device on the table on stationary position!:\n";
+        QOrientationReading::Orientation o1 = tests::orientation[counter%6];
+        tests::drawDevice(o1);
+        tests::pressAnyKey();
+        QTest::qWait(50);   // DO NOT REMOVE - does not work without this!
+
+        if (counter==0) continue;     //prevent from first UNDEFINED VALUE
+
+
+        if (o1!=o2){
+            j++;
+            tmp.append("Orientation: expected/measured: \n");
+            tmp.append(tests::orientationAsString(o1));
+            tmp.append("!=");
+            tmp.append(tests::orientationAsString(o2));
+            tmp.append("\n");
+        }
+
+
+        //acceleration
+        qreal tmpX = tests::acce_array[counter%6][0];
+        qreal tmpY = tests::acce_array[counter%6][1];
+        qreal tmpZ = tests::acce_array[counter%6][2];
+        qreal x = acceReading->x();
+        qreal y = acceReading->y();
+        qreal z = acceReading->z();
+
+        QString accTmp;
+        int tmpK = k;
+        if (qAbs(x-tmpX)>tests::THRESHOLD){
+            k++;
+            accTmp.append(tests::debugMessage("Acceleration X: ",tmpX, x, tests::THRESHOLD));
+        }
+
+        if (qAbs(y-tmpY)>tests::THRESHOLD){
+            k++;
+            accTmp.append(tests::debugMessage("Acceleration Y: ",tmpY, y, tests::THRESHOLD));
+        }
+
+        if (qAbs(z-tmpZ)>tests::THRESHOLD){
+            k++;
+            accTmp.append(tests::debugMessage("Acceleration Z: ",tmpZ, z, tests::THRESHOLD));
+        }
+        if (k>tmpK){
+            tmp.append("Acceleration failure when in ");
+            tmp.append(tests::orientationAsString(o2));
+            tmp.append("\n");
+            tmp.append(accTmp);
+        }
+
+        //rotation
+        QString rotTmp;
+        tmpX = tests::rot_array[counter%6][0];
+        tmpY = tests::rot_array[counter%6][1];
+        x = rotReading->x();
+        y = rotReading->y();
+        if (hasZ){
+            rot_x[counter-1]=rotReading->x();
+            rot_y[counter-1]=rotReading->y();
+            rot_z[counter-1]=rotReading->z();
+        }
+        int tmpL = l;
+        // not as straight-forward
+        if (qAbs(x-tmpX)>tests::ROT_THRESHOLD){
+            l++;
+            rotTmp.append(tests::debugMessage("Rotation X: ", tmpX, x, tests::ROT_THRESHOLD));
+        }
+
+        if (tmpY<y-tests::ROT_THRESHOLD || tmpY>y+tests::ROT_THRESHOLD){
+            l++;
+            rotTmp.append(tests::debugMessage("Rotation Y: ", tmpY, y, tests::ROT_THRESHOLD));
+        }
+        if (l>tmpL){
+            tmp.append("Rotation failure when in ");
+            tmp.append(tests::orientationAsString(o2));
+            tmp.append("\n");
+            tmp.append(rotTmp);
+        }
+
+
+        //magnetometer
+        magge_x[counter-1]=maggeReading->x();
+        magge_y[counter-1]=maggeReading->y();
+        magge_z[counter-1]=maggeReading->z();
+
+        //        qDebug()<<" magge x="<<magge_x[i-1]<<", y="<<magge_y[i-1]<<", z="<<magge_z[i-1];
+
+        //compass
+        compass_azimuth[counter-1] = compassReading->azimuth();
+        compass_level[counter-1] = compassReading->calibrationLevel();
+        //        qDebug()<<" compass = "<< compass_azimuth[i-1];
+        //        if (hasZ){
+        //            qDebug()<<" rotation = x "<<rot_x[i-1];
+        //            qDebug()<<" rotation = y "<<rot_y[i-1];
+        //            qDebug()<<" rotation = z "<<rot_z[i-1];
+        //        }
+
+
+        if (counter==4){
+            isStationary = true;
+            qDebug()<<"Keep the device on the table on stationary position!:\n";
+            qDebug()<<"Test continues after a while";            
+            QTest::qWait(2000);   // DO NOT REMOVE - does not work without this!
+            isStationary = false;
+        }
+    }
+
+
+    //magnetometer: same magnitude, opposite values
+    // x-axis comparison, 1 and 2
+    // y-axis comparison, 0 and 5
+    // z-axis comparison, 3 and 4
+    int rangeIndex = magnetometer.outputRange();
+    qreal threshold = (magnetometer.outputRanges().at(rangeIndex).maximum - magnetometer.outputRanges().at(rangeIndex).minimum)/10;
+
+    QString msg;
+    if (!tests::testMagge(magge_x[1], magge_x[2], threshold, msg)){
+        tmp.append("Magnetometer failure (x-axis):");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge(magge_y[0], magge_y[5], threshold, msg)){
+        tmp.append("Magnetometer failure (y-axis):");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge(magge_z[3], magge_z[4], threshold, msg)){
+        tmp.append("Magnetometer failure (z-axis):");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+
+    //magnetometer: one big value, two small values
+    // x-axis comparison, 1 and 2
+    // y-axis comparison, 0 and 5
+    // z-axis comparison, 3 and 4
+    if (!tests::testMagge2(magge_x[1], magge_y[1], magge_z[1], msg)){
+        tmp.append("Magnetometer x: not bigger than y, z :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge2(magge_x[2], magge_y[2], magge_z[2], msg)){
+        tmp.append("Magnetometer x: not bigger than y, z :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge2(magge_y[0], magge_x[0], magge_z[0], msg)){
+        tmp.append("Magnetometer y: not bigger than x, z :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge2(magge_y[5], magge_x[5], magge_z[5], msg)){
+        tmp.append("Magnetometer y: not bigger than x, z :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge2(magge_z[3], magge_x[3], magge_y[3], msg)){
+        tmp.append("Magnetometer z: not bigger than x, y :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+    if (!tests::testMagge2(magge_z[4], magge_x[4], magge_y[4], msg)){
+        tmp.append("Magnetometer z: not bigger than x, y :");
+        tmp.append(msg);
+        msg.clear();
+        j++;
+    }
+
+    //rotation
+    if (hasZ){
+        qDebug()<<"Is magnetic north pole rotation sensor's external entity";
+        if (tests::confirm()){
+            for (int i=0; i<6; i++){
+                if (!(tests::testRot(compass_azimuth[i], rot_z[i], msg))){
+                    tmp.append(msg);
+                    msg.clear();
+                }
+            }
+        }
+    }
+
+    // compass: 1&2, 3&4
+    // azimuth will be projected to horizontal plane
+    // top up & top down (5&0): too much variation, NOT tested
+    // left up & right up (1&2): 180 diff
+    // face up & face down (3&4): should be the same
+    // take calibration level into account
+    int index[6]={1,2,3,4};
+
+    for (int i=0; i<3; i++){
+        if (compass_level[index[i*2]]< 0.1 || compass_level[index[i*2+1]]< 0.1)
+            continue;
+
+        qreal val1 = compass_azimuth[index[i*2]];
+        qreal val2 = compass_azimuth[index[i*2+1]];
+        //        QString num;
+        //        qDebug()<<" Compass testing val1 = "<<num.setNum(val1)<< " val2 = "<<num.setNum(val2);
+
+        if (i==0){
+            val1 = ((int)val1+180)%360;
+        }
+
+        if (!(tests::testCompass(val1, val2, msg))){
+            tmp.append(msg);
+            msg.clear();
+            j++;
+        }
+    }
+
+    qDebug()<< "Do you have a real compass in use: \n";
+    bool isYes = tests::confirm();
+    if (isYes){
+        qDebug()<<"Put the device in following position, and head it towards compass north:\n";
+        QOrientationReading::Orientation o1 = tests::orientation[4];
+        tests::drawDevice(o1);
+        tests::pressAnyKey();
+        QTest::qWait(50);   // DO NOT REMOVE - does not work without this!
+        qreal azimuth = compassReading->azimuth();
+
+        if (azimuth>20 && azimuth<340){
+            j++;
+            tmp.append("Instead of being 0, compass north gives ");
+            QString num;
+            num.setNum(azimuth);
+            tmp.append(num);
+            tmp.append("\n");
+        }
+    }
+
+
+
+    QVERIFY2(tmp.size()<2, tmp.toLatin1().data());
+}
+
+
+void test_manual::testDataRate(){
+    QVERIFY2(dataRateString.size()==0, dataRateString.toLatin1().data());
+    dataRateString.clear();
+}
+
+void test_manual::testOutputRange(){
+    QVERIFY2(dataRangeString.size()==0, dataRangeString.toLatin1().data());
+    dataRangeString.clear();
+}
+
+void test_manual::testResolution(){
+    QVERIFY2(resolutionString.size()==0, resolutionString.toLatin1().data());
+    resolutionString.clear();
+}
+
+
+
+QTEST_MAIN(test_manual)
+
+#include "test_manual.moc"