Changed URLs. Added open/close to QBuffer buffers.
[speedfreak] / Client / accelerometer.cpp
index 0f70d0b..5c16c98 100644 (file)
@@ -1,3 +1,12 @@
+/*
+ * Accelerometer class to access the device accelerometer
+ *
+ * @author      Rikhard Kuutti <rikhard.kuutti@fudeco.com>
+ * @author      Kai Rasilainen 
+ * @copyright   (c) 2010 Speed Freak team
+ * @license     http://opensource.org/licenses/gpl-license.php GNU Public License
+ */
+
 #include "accelerometer.h"
 #include "math.h"
 
 
 #define kFilteringFactor    0.1
 #define kGravity            9.81
+#define kFileName           "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
 
 static int sampleIndex=0;
 
+/**
+ * Default constructor for Accelerometer class
+ *
+ */
 Accelerometer::Accelerometer()
 {
-    QTimer *timer = new QTimer(this);
+    calculate = new Calculate();
+
+    timer = new QTimer(this);
     connect(timer, SIGNAL(timeout()), this, SLOT(processData()));
-    sampleRate = 100;
-    timer->start(sampleRate);
-    now.restart();
+    sampleRate = 40;
+    initValues();
+}
+
+/**
+ * Constructor for Accelerometer class that takes accelerometer sample rate as parameter
+ *
+ * @param p_SampleRate the desired sample rate of accelerometer in milliseconds
+ */
+Accelerometer::Accelerometer(int p_SampleRate)
+{
+    calculate = new Calculate();
 
+    timer = new QTimer(this);
+    connect(timer, SIGNAL(timeout()), this, SLOT(processData()));
+    sampleRate = p_SampleRate;
     initValues();
 }
 
-Accelerometer::~Accelerometer() {
+/**
+ * Default destructor for Accelerometer class
+ *
+ */
+Accelerometer::~Accelerometer()
+{
 }
 
-void Accelerometer::start() {
+/**
+ * Start measuring
+ *
+ */
+void Accelerometer::start()
+{
+    initValues();
+    calibrate();
     timer->start(sampleRate);
     now.restart();
 }
 
-void Accelerometer::initValues() {
-    accelerationX=0;
-    accelerationY=0;
-    accelerationZ=0;
-    trueAccelerationX=0;
-    trueAccelerationY=0;
-    trueAccelerationZ=0;
-    previousAccelerationX=0;
-    previousAccelerationY=0;
-    previousAccelerationZ=0;
-    previousSpeed=0;
-    currentSpeed=0;
-    currentAcceleration=0;
-    previousAcceleration=0;
-    totalAcceleration=0;
-    intervalTime=0;
-    totalTime=0;
-    distanceTraveled=0;
-    lastDistanceTraveled=0;
-    averageSpeed=0;
-    sampleRate=0;
-}
-
-void Accelerometer::stop() {
+/**
+ * Init class members
+ *
+ */
+void Accelerometer::initValues()
+{
+    calculate->reset();
+    accelerationX = 0;
+    accelerationY = 0;
+    accelerationZ = 0;
+    trueAccelerationX = 0;
+    trueAccelerationY = 0;
+    trueAccelerationZ = 0;
+    previousAccelerationX = 0;
+    previousAccelerationY = 0;
+    previousAccelerationZ = 0;
+    previousSpeed = 0;
+    currentSpeed = 0;
+    currentAcceleration = 0;
+    previousAcceleration = 0;
+    totalAcceleration = 0;
+    intervalTime = 0;
+    totalTime = 0;
+    distanceTraveled = 0;
+    lastDistanceTraveled = 0;
+    averageSpeed = 0;
+    sampleRate = 0;
+    firstRun = true;
+    calibrationX = 0;
+    calibrationY = 0;
+    calibrationZ = 0;
+}
+
+/**
+  * Calibrate. Purpose of this function is to calibrate
+  * accelerometer when stationary.
+  *
+  */
+void Accelerometer::calibrate(void)
+{
+    unsigned int iteration = 0;
+
+    do {
+        // Opening the file must be done inside the loop
+        // or else the values obtained from file.readLine();
+        // will be empty for all but the first iteration
+        QFile file(kFileName);
+        if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
+        {
+            return;
+        }
+
+        QByteArray line;
+        QRegExp rx("([0-9-]+) ([0-9-]+) ([0-9-]+)");
+
+        // Read data, parse with regular expressions and process it
+        line = file.readLine();
+        rx.indexIn(line);
+
+        int sampleX = rx.cap(1).toInt();
+        int sampleY = rx.cap(2).toInt();
+        int sampleZ = rx.cap(3).toInt();
+
+        calibrationX = calibrationX + sampleX; // Accumulate Samples
+        calibrationY = calibrationY + sampleY; // for all axes.
+        calibrationZ = calibrationZ + sampleZ;
+
+        iteration++;
+
+        file.close();
+    } while(iteration != 1024);       // 1024 times
+
+    calibrationX = calibrationX>>10;  // division by 1024
+    calibrationY = calibrationY>>10;
+    calibrationZ = calibrationZ>>10;
+}
+
+/**
+ * Stop measuring
+ *
+ */
+void Accelerometer::stop()
+{
     timer->stop();
 }
 
-void Accelerometer::setSampleRate(int pSampleRate) {
+/**
+ * Set the sample rate of accelerometer
+ *
+ * @param pSampleRate desired sample rate
+ */
+void Accelerometer::setSampleRate(int pSampleRate)
+{
     sampleRate = pSampleRate;
 }
 
-int Accelerometer::getSampleRate() {
+/**
+ * Get the sample rate of accelerometer
+ *
+ * @return sampleRate the sample rate of the accelerometer in milliseconds
+ */
+int Accelerometer::getSampleRate()
+{
     return sampleRate;
 }
 
-qreal Accelerometer::getCurrentAcceleration() {
+qreal Accelerometer::getCurrentAcceleration()
+{
     return currentAcceleration;
 }
 
-qreal Accelerometer::getPreviousTotalAcceleration() {
+qreal Accelerometer::getPreviousTotalAcceleration()
+{
     return previousAcceleration;
 }
 
-qreal Accelerometer::getTotalAcceleration() {
+qreal Accelerometer::getTotalAcceleration()
+{
     return totalAcceleration;
 }
 
-qreal Accelerometer::getDistanceTraveled() {
+qreal Accelerometer::getDistanceTraveled()
+{
     return distanceTraveled;
 }
 
-qreal Accelerometer::getLastDistanceTraveled() {
+qreal Accelerometer::getLastDistanceTraveled()
+{
     return lastDistanceTraveled;
 }
 
-qreal Accelerometer::getAverageSpeed() {
+qreal Accelerometer::getAverageSpeed()
+{
     return averageSpeed;
 }
 
-qreal Accelerometer::getTrueAccelerationX() {
+qreal Accelerometer::getTrueAccelerationX()
+{
     return trueAccelerationX;
 }
 
-qreal Accelerometer::getTrueAccelerationY() {
+qreal Accelerometer::getTrueAccelerationY()
+{
     return trueAccelerationY;
 }
 
-qreal Accelerometer::getTrueAccelerationZ() {
+qreal Accelerometer::getTrueAccelerationZ()
+{
     return trueAccelerationZ;
 }
 
-qreal Accelerometer::getPreviousSpeed() {
+qreal Accelerometer::getPreviousSpeed()
+{
     return previousSpeed;
 }
 
-qreal Accelerometer::getCurrentSpeed() {
+qreal Accelerometer::getCurrentSpeed()
+{
     return currentSpeed;
 }
 
-qreal Accelerometer::getintervalTime() {
+qreal Accelerometer::getIntervalTime()
+{
     return intervalTime;
 }
 
+qreal Accelerometer::getTotalTime()
+{
+    return totalTime;
+}
+
+int Accelerometer::getCalibrationX()
+{
+    return calibrationX;
+}
+
+int Accelerometer::getCalibrationY()
+{
+    return calibrationY;
+}
+
+int Accelerometer::getCalibrationZ()
+{
+    return calibrationZ;
+}
+
 /**
  * Processes Accelerometer data
  *
+ * Opens the accelerometer value file for reading and reads and parses accelerometer values.
+ * Forwards data to Calculate class for processing
+ *
  */
 void Accelerometer::processData()
 {
-    QFile file("/sys/class/i2c-adapter/i2c-3/3-001d/coord");
-    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+    QFile file(kFileName);
+    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
+    {
         return;
+    }
 
     // Read data, parse with regular expressions and process it
     QByteArray line = file.readLine();
@@ -130,51 +278,56 @@ void Accelerometer::processData()
 
     smoothData(rx.cap(1).toInt(), rx.cap(2).toInt(), rx.cap(3).toInt());
 
-    trueAccelerationX = (accelerationX - previousAccelerationX)/1000*kGravity;
-    trueAccelerationY = (accelerationY - previousAccelerationY)/1000*kGravity;
-    trueAccelerationZ = (accelerationZ - previousAccelerationZ)/1000*kGravity;
+    // Apply calibration
+    accelerationX = accelerationX - calibrationX;
+    accelerationX = accelerationY - calibrationY;
+    accelerationX = accelerationZ - calibrationZ;
+
+    // If the function is run the first time, make sure that there
+    // are no differences with previous and current acceleration
+    if (firstRun) {
+        previousAccelerationX = accelerationX;
+        previousAccelerationY = accelerationY;
+        previousAccelerationZ = accelerationZ;
+        firstRun = false;
+    }
+
+    // Discrimination window for acceleration values
+    /*if ( fabs(accelerationX) < 20 ) { accelerationX = 0; }
+      if ( fabs(accelerationY) < 20 ) { accelerationY = 0; }
+      if ( fabs(accelerationZ) < 20 ) { accelerationZ = 0; }*/
+
+    // Calculate the current acceleration for each axis
+    trueAccelerationX = (accelerationX - previousAccelerationX) /*/ 1000 * kGravity*/;
+    trueAccelerationY = (accelerationY - previousAccelerationY) /*/ 1000 * kGravity*/;
+    trueAccelerationZ = (accelerationZ - previousAccelerationZ) /*/ 1000 * kGravity*/;
+
+    // Discrimination window for acceleration values
+    if ( fabs(trueAccelerationX) < 20 ) { trueAccelerationX = 0; }
+    if ( fabs(trueAccelerationY) < 20 ) { trueAccelerationY = 0; }
+    if ( fabs(trueAccelerationZ) < 20 ) { trueAccelerationZ = 0; }
 
     previousAccelerationX = accelerationX;
     previousAccelerationY = accelerationY;
     previousAccelerationZ = accelerationZ;
 
     currentAcceleration = sqrt(trueAccelerationX * trueAccelerationX +
-                           trueAccelerationY * trueAccelerationY +
-                           trueAccelerationZ * trueAccelerationZ );
-
-    totalAcceleration = currentAcceleration - previousAcceleration;
+                               trueAccelerationY * trueAccelerationY +
+                               trueAccelerationZ * trueAccelerationZ );
 
-    totalAcceleration = fabs(totalAcceleration);
-
-    previousAcceleration = currentAcceleration;
-
-    // v = v0 + at
-    // x = x0 + v0t + (at^2)/2
-    // v = (v + v0)/2
+    // Discrimination window for currentAcceleration
+    if ( fabs(currentAcceleration) < 20 ) { currentAcceleration = 0; }
 
+    // Measure time interval
     intervalTime = now.restart();
     intervalTime = intervalTime/1000; // millisecs to secs
     totalTime = totalTime + intervalTime;
 
-    // filter noise
-    // TODO: do this in smoothdata: implement a better filter.
-    if (totalAcceleration > 0.02) {
-        currentSpeed = ( previousSpeed + ( totalAcceleration * intervalTime ) / 2 );
-    } else {
-        currentSpeed = 0;
-    }
+    // Using calculate class to calculate velocity and distance etc.
+    calculate->calculateParameters(currentAcceleration,intervalTime );
 
-    // filter noise
-    if (currentSpeed > 0.02) {
-        distanceTraveled = ( lastDistanceTraveled + ( ( currentSpeed + previousSpeed ) * intervalTime) / 2 );
-    } else {
-        //distanceTraveled = 0;
-    }
-
-    averageSpeed = distanceTraveled / totalTime;
-
-    previousSpeed = currentSpeed;
-    lastDistanceTraveled = distanceTraveled;
+    currentSpeed = calculate->getCurrentSpeed();
+    distanceTraveled = calculate->getDistanceTraveled();
 
     file.close();
 }
@@ -182,18 +335,21 @@ void Accelerometer::processData()
 /**
  * Smooths Accelerometer data
  *
- * @param x Accelerometers x-axis raw input
- * @param y Accelerometers y-axis raw input
- * @param z Accelerometers z-axis raw input
+ * @param x accelerometer's x-axis input
+ * @param y accelerometer's y-axis input
+ * @param z accelerometer's z-axis input
  */
-void Accelerometer::smoothData(qreal x, qreal y, qreal z) {
+void Accelerometer::smoothData(qreal x, qreal y, qreal z)
+{
     accelerationX = x;
     accelerationY = y;
     accelerationZ = z;
-    if(sampleIndex>0) {
+    if (sampleIndex > 0)
+    {
         accelerationX = previousAccelerationX + (accelerationX-previousAccelerationX) * kFilteringFactor;
         accelerationY = previousAccelerationY + (accelerationY-previousAccelerationY) * kFilteringFactor;
         accelerationZ = previousAccelerationZ + (accelerationZ-previousAccelerationZ) * kFilteringFactor;
     }
     sampleIndex++;
 }
+