From 10fde8e4f0fbaf96627e95c9ffab33b2e49c91a4 Mon Sep 17 00:00:00 2001
From: Simon Ottenhaus <simon.ottenhaus@kit.edu>
Date: Mon, 23 Jun 2014 14:12:35 +0200
Subject: [PATCH] Added Logging

---
 .gitignore                                    |  3 +-
 .../WeissHapticSensorsUnitTest/startGui.sh    |  8 +++
 .../WeissHapticSensorsUnitTest/tactile.html   | 54 +++++++++++++++++++
 .../WeissHapticSensorsUnit/CMakeLists.txt     |  4 +-
 .../WeissHapticSensor/AbstractInterface.cpp   | 53 ++++++++++++++++--
 .../WeissHapticSensor/AbstractInterface.h     | 11 +++-
 .../WeissHapticSensor/BinaryLogger.cpp        |  6 +++
 .../drivers/WeissHapticSensor/BinaryLogger.h  |  1 +
 .../drivers/WeissHapticSensor/CMakeLists.txt  |  2 +
 .../WeissHapticSensor/SerialInterface.cpp     | 25 ++-------
 .../WeissHapticSensor/SerialInterface.h       |  8 ++-
 .../drivers/WeissHapticSensor/TextWriter.cpp  | 20 +++++++
 .../drivers/WeissHapticSensor/TextWriter.h    | 21 ++++++++
 .../WeissHapticSensor/WeissHapticSensor.cpp   | 33 ++++++++++--
 .../WeissHapticSensor/WeissHapticSensor.h     |  6 +++
 source/RobotAPI/units/HapticObserver.cpp      | 12 +++--
 source/RobotAPI/units/HapticObserver.h        | 16 +++++-
 17 files changed, 238 insertions(+), 45 deletions(-)
 create mode 100755 scenarios/WeissHapticSensorsUnitTest/startGui.sh
 create mode 100755 scenarios/WeissHapticSensorsUnitTest/tactile.html
 create mode 100644 source/RobotAPI/drivers/WeissHapticSensor/TextWriter.cpp
 create mode 100644 source/RobotAPI/drivers/WeissHapticSensor/TextWriter.h

diff --git a/.gitignore b/.gitignore
index 36b9b1d57..f0dad452b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,5 +45,6 @@ data/dbdump/
 # Generated Scenario Files
 scenarios/*/startScenario.sh
 scenarios/*/stopScenario.sh
-scenarios/*/startGui.sh
+scenarios/*/ttyACM*.js
+scenarios/*/ttyACM*.log
 
diff --git a/scenarios/WeissHapticSensorsUnitTest/startGui.sh b/scenarios/WeissHapticSensorsUnitTest/startGui.sh
new file mode 100755
index 000000000..e2f4b07c6
--- /dev/null
+++ b/scenarios/WeissHapticSensorsUnitTest/startGui.sh
@@ -0,0 +1,8 @@
+export CORE_PATH=../../../Core
+export GUI_PATH=../../../Gui
+
+export SCRIPT_PATH=$CORE_PATH/build/bin
+export GUI_BIN_PATH=$GUI_PATH/build/bin
+
+# Gui
+$SCRIPT_PATH/startApplication.sh $GUI_BIN_PATH/ArmarXGuiRun &
diff --git a/scenarios/WeissHapticSensorsUnitTest/tactile.html b/scenarios/WeissHapticSensorsUnitTest/tactile.html
new file mode 100755
index 000000000..c86869f07
--- /dev/null
+++ b/scenarios/WeissHapticSensorsUnitTest/tactile.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="de-DE">
+<head>
+<meta charset="utf-8">    
+<title>Tactile Sensor Data Explorer</title>
+<link rel="stylesheet" type="text/css" href="svg-export.css"/>
+<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
+<script>
+sensors = [];
+</script>
+<script src="ttyACM0.js"></script>
+<script src="ttyACM1.js"></script>
+<style type="text/css">
+#out {
+	font-size: 10px;
+	font-family: Verdana, sans;
+}
+</style>
+</head>
+<body>
+<div id="buttons"></div>
+<div id="out"></div>
+<script>
+
+var displayData = function(data) {
+	var s = 40;
+	var str = '<div style="position: relative; width:' + (data[0].length * s) + 'px; height:' + (data.length * s) + 'px;">';
+	for(var y = 0; y < data.length; y++) {
+		var row = data[y];
+		
+		for(var x = 0; x < row.length; x++) {
+			str += '<div style="top:' + (y * s) + 'px; left:' + (x * s) + 'px; width: '+s+'px; height: '+s+'px; position: absolute; text-align:center; line-height:'+s+'px; ">' + row[x] + '</div>';
+		}
+	}
+	str += '</div>';
+	return str;
+};
+
+var pos = 0;
+var sensor = sensors[0];
+var formatDate = function(date) {
+	return date.getYear() + "-" + ("00" + date.getMonth()).slice(-2) + "-" + ("00" + date.getDate()).slice(-2) + " " + ("00" + date.getHours()).slice(-2) + ":" + ("00" + date.getMinutes()).slice(-2) + ":" + ("00" + date.getSeconds()).slice(-2) + "." + ("000" + date.getMilliseconds()).slice(-3);
+};
+var update = function() {
+	$("#out").html(sensor.device + ", tag=" + sensor.tag + "<br />Frame " + pos + "/" + (sensor.data.length - 1) + " t= " + formatDate(new Date(sensor.data[pos][0]/1000)) + displayData(sensor.data[pos][1]));
+}
+var changeFrameGen = function(delta) { return function() { pos = Math.max(0, Math.min(sensor.data.length - 1, pos + delta)); update(); }; };
+var buttonGen = function(text, delta) { return $("<button>"+text+"</button>").click(changeFrameGen(delta)); };
+$("#buttons").append("navigate: ").append(buttonGen("-100", -100)).append(buttonGen("-10", -10)).append(buttonGen("-1", -1)).append(buttonGen("+1", +1)).append(buttonGen("+10", +10)).append(buttonGen("+100", +100));
+update();
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt b/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt
index d2d552863..e49b35907 100644
--- a/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt
+++ b/source/RobotAPI/applications/WeissHapticSensorsUnit/CMakeLists.txt
@@ -8,8 +8,8 @@ if (Eigen3_FOUND)
         ${Eigen3_INCLUDE_DIR})
 endif()
 
-set(COMPONENT_LIBS ArmarXInterfaces ArmarXCore ArmarXCoreEigen3Variants WeissHapticSensor)
+set(COMPONENT_LIBS ArmarXInterfaces ArmarXCore ArmarXCoreObservers ArmarXCoreEigen3Variants WeissHapticSensor RobotAPIUnits)
 
-set(EXE_SOURCE main.cpp)
+set(EXE_SOURCE main.cpp WeissHapticSensorsUnitApp.h)
 
 armarx_add_component_executable("${EXE_SOURCE}")
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.cpp b/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.cpp
index 973635b44..a81825709 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.cpp
+++ b/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.cpp
@@ -9,12 +9,39 @@
 #include <stdexcept>
 
 
-AbstractInterface::AbstractInterface() :
-    connected(false) {
+AbstractInterface::AbstractInterface()
+    : connected(false), log(NULL)
+{
+
 }
 
 AbstractInterface::~AbstractInterface() {
-    // TODO Auto-generated destructor stub
+    if(log != NULL)
+    {
+        delete log;
+    }
+}
+
+int AbstractInterface::read(unsigned char *buf, unsigned int len)
+{
+    int res = readInternal(buf, len);
+
+    if(log != NULL)
+    {
+        log->logRead(buf, res);
+    }
+
+    return res;
+}
+
+int AbstractInterface::write(unsigned char *buf, unsigned int len)
+{
+    if(log != NULL)
+    {
+        log->logWrite(buf, len);
+    }
+
+    return writeInternal(buf, len);
 }
 
 
@@ -57,6 +84,19 @@ void AbstractInterface::fireAndForgetCmd( unsigned char id, unsigned char *paylo
     }
 }
 
+void AbstractInterface::startLogging(std::string file)
+{
+    log = new BinaryLogger(file);
+}
+
+void AbstractInterface::logText(std::string message)
+{
+    if(log != NULL)
+    {
+        log->logText(message);
+    }
+}
+
 Response AbstractInterface::receiveWithoutChecks()
 {
     int res;
@@ -124,6 +164,7 @@ int AbstractInterface::receive( msg_t *msg )
     unsigned short checksum = 0x50f5;	// Checksum over preamble (0xaa 0xaa 0xaa)
     unsigned int sync;
 
+    logText("read preamble");
     // Syncing - necessary for compatibility with serial interface
     sync = 0;
     while( sync != MSG_PREAMBLE_LEN )
@@ -191,9 +232,11 @@ int AbstractInterface::receive( msg_t *msg )
     checksum = Checksum::Update_crc16( msg->data.data(), msg->len + 2, checksum );
     if ( checksum != 0 )
     {
+        logText("CHECKSUM ERROR");
         throw ChecksumErrorException("Checksum error");
     }
 
+    logText("receive done.");
     return msg->len + 8;
 }
 
@@ -203,6 +246,8 @@ int AbstractInterface::send(unsigned char id, unsigned int len, unsigned char *d
     unsigned short crc;
     int i, res;
 
+    logText("write preamble");
+
     // Preamble
     for ( i = 0; i < MSG_PREAMBLE_LEN; i++ ) header[i] = MSG_PREAMBLE_BYTE;
 
@@ -233,6 +278,8 @@ int AbstractInterface::send(unsigned char id, unsigned int len, unsigned char *d
 
     delete[] buf;
 
+    logText("send done.");
+
     return len + 8;
 }
 
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.h b/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.h
index 5c01b9fc5..f8d6c1b9a 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.h
+++ b/source/RobotAPI/drivers/WeissHapticSensor/AbstractInterface.h
@@ -3,6 +3,7 @@
 
 #include <string>
 #include "Types.h"
+#include "BinaryLogger.h"
 
 
 #define MSG_PREAMBLE_BYTE		0xaa
@@ -29,8 +30,8 @@ public:
     virtual ~AbstractInterface();
     virtual int open() = 0;
     virtual void close() = 0;
-    virtual int read( unsigned char *buf, unsigned int len) = 0;
-    virtual int write( unsigned char *buf, unsigned int len) = 0;
+    int read( unsigned char *buf, unsigned int len);
+    int write( unsigned char *buf, unsigned int len);
 
     bool IsConnected() const { return connected; }
 
@@ -43,12 +44,18 @@ public:
     Response receiveWithoutChecks();
     void fireAndForgetCmd( unsigned char id, unsigned char *payload, unsigned int len, bool pending );
 
+    void startLogging(std::string file);
+    void logText(std::string message);
 
 protected:
     bool connected;
 
+    virtual int readInternal( unsigned char *buf, unsigned int len) = 0;
+    virtual int writeInternal( unsigned char *buf, unsigned int len) = 0;
+
 private:
     friend std::ostream& operator<<(std::ostream&, const AbstractInterface&);
+    BinaryLogger* log;
 };
 
 std::ostream& operator<<(std::ostream &strm, const AbstractInterface &a);
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.cpp b/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.cpp
index b3a494138..40c394097 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.cpp
+++ b/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.cpp
@@ -32,3 +32,9 @@ void BinaryLogger::logWrite(unsigned char *buf, unsigned int len)
     log << std::endl;
     log.flush();
 }
+
+void BinaryLogger::logText(std::string message)
+{
+    log << message << std::endl;
+    log.flush();
+}
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.h b/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.h
index d16c85ca6..535786e85 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.h
+++ b/source/RobotAPI/drivers/WeissHapticSensor/BinaryLogger.h
@@ -11,6 +11,7 @@ public:
 
     void logRead(unsigned char *buf, unsigned int len);
     void logWrite(unsigned char *buf, unsigned int len);
+    void logText(std::string message);
 
 private:
     std::ofstream log;
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/CMakeLists.txt b/source/RobotAPI/drivers/WeissHapticSensor/CMakeLists.txt
index 01d560fb8..60c8611f2 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/CMakeLists.txt
+++ b/source/RobotAPI/drivers/WeissHapticSensor/CMakeLists.txt
@@ -21,6 +21,7 @@ set(LIB_FILES
     WeissHapticSensor.cpp
     AbstractInterface.cpp
     BinaryLogger.cpp
+    TextWriter.cpp
     Checksum.cpp
     SerialInterface.cpp
     TactileSensor.cpp
@@ -30,6 +31,7 @@ set(LIB_HEADERS
     WeissHapticSensor.h
     AbstractInterface.h
     BinaryLogger.h
+    TextWriter.h
     Checksum.h
     Response.h
     SerialInterface.h
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.cpp b/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.cpp
index b9bdfe5f0..77bc6b49f 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.cpp
+++ b/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.cpp
@@ -35,17 +35,13 @@ static inline tcflag_t __bitrate_to_flag( unsigned int bitrate )
 
 
 SerialInterface::SerialInterface(const char *device, unsigned int bitrate)
-    : log(NULL)
 {
     this->device = device;
     this->bitrate = bitrate;
 }
 
 SerialInterface::~SerialInterface() {
-    if(log != NULL)
-    {
-        delete log;
-    }
+
 }
 
 int SerialInterface::open() {
@@ -122,7 +118,7 @@ void SerialInterface::close()
     connected = false;
 }
 
-int SerialInterface::read( unsigned char *buf, unsigned int len)
+int SerialInterface::readInternal( unsigned char *buf, unsigned int len)
 {
     int res;
 
@@ -132,21 +128,11 @@ int SerialInterface::read( unsigned char *buf, unsigned int len)
         std::cerr << "Failed to read from serial device" << std::endl;
     }
 
-    if(log != NULL)
-    {
-        log->logRead(buf, res);
-    }
-
     return res;
 
 }
-int SerialInterface::write( unsigned char *buf, unsigned int len)
+int SerialInterface::writeInternal( unsigned char *buf, unsigned int len)
 {
-    if(log != NULL)
-    {
-        log->logWrite(buf, len);
-    }
-
     return( ::write( fd, (void *) buf, len ) );
 }
 
@@ -155,8 +141,3 @@ std::string SerialInterface::toString() const
     return str(boost::format("SerialInterface(connected=%1%, device=%2%, bitrate=%3%, fd=%4%)")
             % connected % device % bitrate % fd);
 }
-
-void SerialInterface::startLogging(std::string file)
-{
-    log = new BinaryLogger(file);
-}
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.h b/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.h
index e5c9b396b..a2bb216ce 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.h
+++ b/source/RobotAPI/drivers/WeissHapticSensor/SerialInterface.h
@@ -3,7 +3,6 @@
 
 #include "AbstractInterface.h"
 #include <iostream>
-#include "BinaryLogger.h"
 
 
 class SerialInterface : public AbstractInterface {
@@ -13,18 +12,17 @@ public:
 
     virtual int open();
     virtual void close();
-    virtual int read( unsigned char *, unsigned int );
-    virtual int write( unsigned char *, unsigned int );
 
     virtual std::string toString() const;
 
-    void startLogging(std::string file);
+protected:
+    virtual int readInternal( unsigned char *, unsigned int );
+    virtual int writeInternal( unsigned char *, unsigned int );
 
 private:
     const char *device;
     unsigned int bitrate;
     int fd;
-    BinaryLogger* log;
 };
 
 #endif // SERIALINTERFACE_H
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.cpp b/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.cpp
new file mode 100644
index 000000000..021bcc12c
--- /dev/null
+++ b/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.cpp
@@ -0,0 +1,20 @@
+#include "TextWriter.h"
+
+using namespace armarx;
+
+TextWriter::TextWriter(std::string filename)
+{
+    this->file.open(filename.c_str());
+}
+
+TextWriter::~TextWriter()
+{
+    file.close();
+}
+
+void TextWriter::writeLine(std::string message)
+{
+    file << message;
+    file << std::endl;
+    file.flush();
+}
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.h b/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.h
new file mode 100644
index 000000000..d0a87537b
--- /dev/null
+++ b/source/RobotAPI/drivers/WeissHapticSensor/TextWriter.h
@@ -0,0 +1,21 @@
+#ifndef TEXTWRITER_H
+#define TEXTWRITER_H
+
+#include <fstream>
+
+namespace armarx
+{
+    class TextWriter
+    {
+    public:
+        TextWriter(std::string filename);
+        ~TextWriter();
+
+        void writeLine(std::string message);
+
+    private:
+        std::ofstream file;
+    };
+}
+
+#endif
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.cpp b/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.cpp
index ba44fc167..4a5a731cd 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.cpp
+++ b/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.cpp
@@ -1,7 +1,7 @@
 #include "WeissHapticSensor.h"
-#include <Core/util/variants/eigen3/MatrixVariant.h>
-#include <Core/observers/variant/TimestampVariant.h>
 #include "TransmissionException.h"
+#include <boost/regex.hpp>
+#include <boost/format.hpp>
 
 using namespace armarx;
 
@@ -9,17 +9,23 @@ WeissHapticSensor::WeissHapticSensor(std::string device)
     : device(device)
 {
     sensorTask = new RunningTask<WeissHapticSensor>(this, &WeissHapticSensor::frameAcquisitionTaskLoop);
+    boost::smatch match;
+    boost::regex_search( device, match, boost::regex("\\w+$") );
+    this->deviceFileName = match[0];
 }
 
 void WeissHapticSensor::connect()
 {
+
     //cout << "Open Serial" << endl;
     this->interface.reset(new SerialInterface(device.c_str(), 115200));
-    //interface->startLogging(this->deviceFileName + ".transmission.log");
+    interface->startLogging(deviceFileName + ".transmission.log");
     interface->open();
     //cout << *interface << endl;
     this->sensor.reset(new TactileSensor(interface));
 
+    jsWriter.reset(new TextWriter(deviceFileName + ".js"));
+
     //cout << "Stop Periodic Frame Acquisition" << endl;
     sensor->stopPeriodicFrameAcquisition();
 
@@ -33,6 +39,12 @@ void WeissHapticSensor::connect()
     this->tag = sensor->getDeviceTag();
     //cout << boost::format("Sensor Tag = %1%") % tag << endl;
 
+    jsWriter->writeLine(str(boost::format("%s = {};") % deviceFileName));
+    jsWriter->writeLine(str(boost::format("sensors.push(%s);") % deviceFileName));
+    jsWriter->writeLine(str(boost::format("%s.device = \"%s\";") % deviceFileName % device));
+    jsWriter->writeLine(str(boost::format("%s.tag = \"%s\";") % deviceFileName % tag));
+    jsWriter->writeLine(str(boost::format("%s.data = [];") % deviceFileName));
+
     //cout << "Tare Sensor Matrix" << endl;
     //sensor->tareSensorMatrix(1);
 
@@ -90,14 +102,25 @@ void WeissHapticSensor::frameAcquisitionTaskLoop()
                     (*matrix)(y, x) = val;
                 }
             }
-            listenerPrx->reportSensorValues(device, tag, matrix, TimestampVariant::nowPtr());
+            TimestampVariantPtr now = TimestampVariant::nowPtr();
+            writeMatrixToJs(matrix, now);
+            listenerPrx->reportSensorValues(device, tag, matrix, now);
         }
         catch(ChecksumErrorException)
         {
-            ARMARX_WARNING << "Caught ChecksumErrorException, skipping frame";
+            ARMARX_WARNING << "Caught ChecksumErrorException on " << device << ", skipping frame";
         }
     }
 
     cout << this << ": stopPeriodicFrameAcquisition" << endl;
     sensor->stopPeriodicFrameAcquisition();
 }
+
+void WeissHapticSensor::writeMatrixToJs(MatrixFloatPtr matrix, TimestampVariantPtr timestamp)
+{
+    //std::cout << "writeMatrixToJs" << std::endl;
+    if(jsWriter != NULL)
+    {
+        jsWriter->writeLine(str(boost::format("%s.data.push([%i, %s]);") % deviceFileName % timestamp->getTimestamp() % matrix->toJsonRowMajor()));
+    }
+}
diff --git a/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.h b/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.h
index 5f4efb2db..acfaad733 100644
--- a/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.h
+++ b/source/RobotAPI/drivers/WeissHapticSensor/WeissHapticSensor.h
@@ -7,6 +7,9 @@
 #include "TactileSensor.h"
 #include <RobotAPI/interface/units/HapticUnit.h>
 #include <Core/util/variants/eigen3/VariantObjectFactories.h>
+#include "TextWriter.h"
+#include <Core/observers/variant/TimestampVariant.h>
+#include <Core/util/variants/eigen3/MatrixVariant.h>
 
 namespace armarx
 {
@@ -23,14 +26,17 @@ namespace armarx
 
     private:
         RunningTask<WeissHapticSensor>::pointer_type sensorTask;
+        boost::shared_ptr<TextWriter> jsWriter;
         void frameAcquisitionTaskLoop();
         std::string device;
+        std::string deviceFileName;
         boost::shared_ptr<SerialInterface> interface;
         boost::shared_ptr<TactileSensor> sensor;
         bool connected;
         string tag;
         tac_matrix_info_t mi;
         HapticUnitListenerPrx listenerPrx;
+        void writeMatrixToJs(MatrixFloatPtr matrix, TimestampVariantPtr timestamp);
     };
 }
 
diff --git a/source/RobotAPI/units/HapticObserver.cpp b/source/RobotAPI/units/HapticObserver.cpp
index cca4d8b0c..033532980 100644
--- a/source/RobotAPI/units/HapticObserver.cpp
+++ b/source/RobotAPI/units/HapticObserver.cpp
@@ -73,14 +73,18 @@ void HapticObserver::reportSensorValues(const std::string& device, const std::st
         setDataField(device, "mean", Variant(mean));
         setDataField(device, "timestamp", timestampPtr);
     }
-    if(statistics.count(device) > 0)
+    /*if(statistics.count(device) > 0)
     {
         statistics.at(device).add(timestamp->timestamp);
+        HapticSampleStatistics stats = statistics.at(device);
+        long avg = stats.average();
+        float rate = avg == 0 ? 0 : 1000000.0f / (float)avg;
+        setDataField(device, "rate", Variant(rate));
     }
     else
     {
         statistics.insert(std::map<std::string,HapticSampleStatistics>::value_type(device, HapticSampleStatistics(100, timestamp->timestamp)));
-    }
+    }*/
 
     updateChannel(device);
 }
@@ -92,7 +96,7 @@ PropertyDefinitionsPtr HapticObserver::createPropertyDefinitions()
 
 void HapticObserver::updateStatistics()
 {
-    ScopedLock lock(dataMutex);
+    /*ScopedLock lock(dataMutex);
     //ARMARX_LOG << "updateStatistics";
     long now = TimestampVariant::nowLong();
     for (std::map<std::string, HapticSampleStatistics>::iterator it = statistics.begin(); it != statistics.end(); ++it)
@@ -103,5 +107,5 @@ void HapticObserver::updateStatistics()
         float rate = avg == 0 ? 0 : 1000000.0f / (float)avg;
         setDataField(device, "rate", Variant(rate));
         updateChannel(device);
-    }
+    }*/
 }
diff --git a/source/RobotAPI/units/HapticObserver.h b/source/RobotAPI/units/HapticObserver.h
index 88e9d74b6..0ef0de014 100644
--- a/source/RobotAPI/units/HapticObserver.h
+++ b/source/RobotAPI/units/HapticObserver.h
@@ -69,7 +69,7 @@ namespace armarx
             lastTimestamp = timestamp;
         }
 
-        long average(long timestamp)
+        /*long average(long timestamp)
         {
             long sum = timestamp - lastTimestamp;
             for(std::vector<long>::iterator it = deltas.begin(); it != deltas.end(); ++it)
@@ -77,6 +77,20 @@ namespace armarx
                 sum += *it;
             }
             return sum / (deltas.size() + 1);
+        }*/
+
+        long average()
+        {
+            if(deltas.size() == 0)
+            {
+                return 0;
+            }
+            long sum = 0;
+            for(std::vector<long>::iterator it = deltas.begin(); it != deltas.end(); ++it)
+            {
+                sum += *it;
+            }
+            return sum / deltas.size();
         }
 
     private:
-- 
GitLab