diff -r 000000000000 -r 876b1a06bc25 examples/sensors/test_manual/test_manual.cpp --- /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 +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#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)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 (tmpYy+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="<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"