From 65aa38789c3b8da18c04b4d15c5a2d0b52bd8b93 Mon Sep 17 00:00:00 2001
From: Johann Mantel <j-mantel@gmx.net>
Date: Thu, 8 Jul 2021 19:33:57 +0200
Subject: [PATCH] Integrate and shorten the inherited loopOnce method of
 SickScanAdapter

---
 etc/cmake/Findsick_scan_base.cmake            |   11 +-
 .../config/SickLaserUnit.cfg                  |   33 +-
 .../drivers/SickLaserUnit/CMakeLists.txt      |    4 +-
 .../drivers/SickLaserUnit/SickLaserUnit.cpp   |   96 +-
 .../drivers/SickLaserUnit/SickLaserUnit.h     |   16 +-
 .../drivers/SickLaserUnit/SickScanAdapter.cpp | 3598 ++++++++---------
 .../drivers/SickLaserUnit/SickScanAdapter.h   |    6 +
 7 files changed, 1704 insertions(+), 2060 deletions(-)

diff --git a/etc/cmake/Findsick_scan_base.cmake b/etc/cmake/Findsick_scan_base.cmake
index 36714c613..391b22908 100644
--- a/etc/cmake/Findsick_scan_base.cmake
+++ b/etc/cmake/Findsick_scan_base.cmake
@@ -20,8 +20,16 @@ set(HEADER_SEARCH_PATHS
     ${sick_scan_base_DIR}/roswrap/src/cfgsimu/
     ENV CPATH
     /usr/include/
+    #/opt/ros/melodic/include/
+    #/opt/ros/melodic/include/sick_scan/
 )
 
+#find_path(sick_scan_base_INCLUDE_DIR_7 NAMES sick_scan_common.h PATHS ${HEADER_SEARCH_PATHS} NO_DEFAULT_PATH)
+#if(sick_scan_base_INCLUDE_DIR_7)
+#    set(sick_scan_base_INCLUDE_DIRS ${sick_scan_base_INCLUDE_DIR_7})
+#endif()
+#find_library(sick_scan_base_LIBRARIES NAMES libsick_scan_lib.so PATHS /opt/ros/melodic/lib/ NO_DEFAULT_PATH)
+
 find_library(sick_scan_base_LIBRARIES NAMES libsick_scan_generic.so PATHS ${sick_scan_base_DIR}/build NO_DEFAULT_PATH)
 message(STATUS "sick_scan_base_LIBRARIES:${sick_scan_base_LIBRARIES}")
 
@@ -33,10 +41,11 @@ find_path(sick_scan_base_INCLUDE_DIR_4 NAMES dynamic_reconfigure/config_tools.h
 find_path(sick_scan_base_INCLUDE_DIR_5 NAMES sick_scan/SickScanConfig.h PATHS ${HEADER_SEARCH_PATHS} NO_DEFAULT_PATH)
 find_path(sick_scan_base_INCLUDE_DIR_6 NAMES sick_scan/rosconsole_simu.hpp PATHS ${HEADER_SEARCH_PATHS} NO_DEFAULT_PATH)
 
-
 if(sick_scan_base_INCLUDE_DIR_0 AND sick_scan_base_INCLUDE_DIR_1 AND sick_scan_base_INCLUDE_DIR_2 AND sick_scan_base_INCLUDE_DIR_3 AND sick_scan_base_INCLUDE_DIR_4 AND sick_scan_base_INCLUDE_DIR_5 AND sick_scan_base_INCLUDE_DIR_6)
     set(sick_scan_base_INCLUDE_DIRS ${sick_scan_base_INCLUDE_DIR_0} ${sick_scan_base_INCLUDE_DIR_1} ${sick_scan_base_INCLUDE_DIR_2} ${sick_scan_base_INCLUDE_DIR_3} ${sick_scan_base_INCLUDE_DIR_4} ${sick_scan_base_INCLUDE_DIR_5} ${sick_scan_base_INCLUDE_DIR_6})
 endif()
+
+
 message(STATUS "sick_scan_base_INCLUDE_DIRS:${sick_scan_base_INCLUDE_DIRS}")
 
 find_package_handle_standard_args(sick_scan_base DEFAULT_MSG sick_scan_base_INCLUDE_DIRS sick_scan_base_LIBRARIES)
diff --git a/scenarios/SickLaserUnitTest/config/SickLaserUnit.cfg b/scenarios/SickLaserUnitTest/config/SickLaserUnit.cfg
index 19f03edb0..5d6d74f97 100644
--- a/scenarios/SickLaserUnitTest/config/SickLaserUnit.cfg
+++ b/scenarios/SickLaserUnitTest/config/SickLaserUnit.cfg
@@ -167,21 +167,12 @@ ArmarX.SickLaserUnit.angleOffset = 0.0
 ArmarX.SickLaserUnit.devices = Device1; Scanner2
 
 
-# ArmarX.SickLaserUnit.emulateSensor:  overwrite the default Settings and don't connect to Scanner
-#  Attributes:
-#  - Default:            false
-#  - Case sensitivity:   yes
-#  - Required:           no
-#  - Possible values: {0, 1, false, no, true, yes}
-# ArmarX.SickLaserUnit.emulateSensor = false
-
-
 # ArmarX.SickLaserUnit.hostname:  Hostname of the LaserScanner
 #  Attributes:
 #  - Default:            192.168.8.133
 #  - Case sensitivity:   yes
 #  - Required:           no
-# ArmarX.SickLaserUnit.hostname = 192.168.8.133
+ArmarX.SickLaserUnit.hostname = 192.168.8.133
 
 
 # ArmarX.SickLaserUnit.laserScannerTopicName:  No Description
@@ -192,14 +183,6 @@ ArmarX.SickLaserUnit.devices = Device1; Scanner2
 ArmarX.SickLaserUnit.laserScannerTopicName = "SickTopic"
 
 
-# ArmarX.SickLaserUnit.newIpAddress:  New IP address for the LaserScanner
-#  Attributes:
-#  - Default:            ""
-#  - Case sensitivity:   yes
-#  - Required:           no
-# ArmarX.SickLaserUnit.newIpAddress = ""
-
-
 # ArmarX.SickLaserUnit.port:  port to use on the LaserScanner
 #  Attributes:
 #  - Default:            2112
@@ -208,12 +191,11 @@ ArmarX.SickLaserUnit.laserScannerTopicName = "SickTopic"
 ArmarX.SickLaserUnit.port = 2112
 
 
-# ArmarX.SickLaserUnit.protocol:  Either use ASCII or Binary protocol
+# ArmarX.SickLaserUnit.protocol:  No Description
 #  Attributes:
 #  - Default:            ASCII
-#  - Case sensitivity:   yes
+#  - Case sensitivity:   no
 #  - Required:           no
-#  - Possible values: {ASCII, Binary}
 ArmarX.SickLaserUnit.protocol = ASCII
 
 
@@ -240,15 +222,6 @@ ArmarX.SickLaserUnit.rangeMin = 0.01
 ArmarX.SickLaserUnit.scannerType = sick_tim_5xx
 
 
-# ArmarX.SickLaserUnit.sopasProtocolType:  Automatically set to true if the Scanner does not support ASCII communication
-#  Attributes:
-#  - Default:            false
-#  - Case sensitivity:   yes
-#  - Required:           no
-#  - Possible values: {0, 1, false, no, true, yes}
-# ArmarX.SickLaserUnit.sopasProtocolType = false
-
-
 # ArmarX.SickLaserUnit.subscribeDatagram:  subscribe to Datagram in communication or not
 #  Attributes:
 #  - Default:            false
diff --git a/source/RobotAPI/drivers/SickLaserUnit/CMakeLists.txt b/source/RobotAPI/drivers/SickLaserUnit/CMakeLists.txt
index 4f22c48fb..15153b3dc 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/CMakeLists.txt
+++ b/source/RobotAPI/drivers/SickLaserUnit/CMakeLists.txt
@@ -45,11 +45,11 @@ armarx_add_component(
 
     SOURCES
         SickLaserUnit.cpp
-	        #SickScanAdapter.cpp
+	SickScanAdapter.cpp
 
     HEADERS
         SickLaserUnit.h
-	        #SickScanAdapter.h
+	SickScanAdapter.h
 )
 
 
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
index c706c5162..1897cbf13 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp
@@ -32,22 +32,6 @@
 namespace armarx
 {
 
-    std::string protocolToString(ScanProtocol protocol)
-    {
-        std::string protocolStr;
-        switch (protocol)
-        {
-            case ScanProtocol::ASCII:
-                protocolStr = "ASCII";
-                break;
-            case ScanProtocol::Binary:
-                protocolStr = "Binary";
-                break;
-        }
-        return protocolStr;
-    }
-
-
     void SickLaserScanDevice::run()
     {
         while (!task->isStopped())
@@ -87,37 +71,26 @@ namespace armarx
         delete this->scanner; // disconnect scanner
         if (this->useTcp)
         {
-            //this->scanner = new SickScanAdapter(this->ip, this->port, this->timelimit, this->parser, this->colaDialectId);
-            this->scanner = new sick_scan::SickScanCommonTcp(this->ip, this->port, this->timelimit, this->parser, this->colaDialectId);
+            this->scanner = new SickScanAdapter(this->ip, this->port, this->timelimit, this->parser, 'A');
+            //this->scanner = new sick_scan::SickScanCommonTcp(this->ip, this->port, this->timelimit, this->parser, 'A');
         }
         else
         {
             ARMARX_ERROR_S << "TCP is not switched on. Probably hostname or port not set.\n";
             return;
         }
-
-        if (this->emulSensor)
-        {
-            this->scanner->setEmulSensor(true);
-        }
         result = this->scanner->init();
-        this->isSensorInitialized = true;
-        ARMARX_INFO_S << "Scanner initialized.";
+
 
         if (result == sick_scan::ExitSuccess) // OK -> loop again
         {
-            if (this->changeIP)
-            {
-                this->runState = RunState::scannerFinalize;
-            }
-            else
-            {
-                this->runState = RunState::scannerRun; // after initialising switch to run state
-            }
-
+            this->isSensorInitialized = true;
+            ARMARX_INFO_S << "Scanner initialized.";
+            this->runState = RunState::scannerRun; // after initialising switch to run state
         }
         else
         {
+            ARMARX_INFO_S << "Reinitializing scanner.";
             this->runState = RunState::scannerInit; // If there was an error, try to restart scanner
         }
     }
@@ -138,14 +111,9 @@ namespace armarx
 
         //communication parameters
         def->optional(properties.hostname, "hostname", "Hostname of the LaserScanner");
-        def->optional(properties.newIpAddress, "newIpAddress", "New IP address for the LaserScanner");
         def->optional(properties.port, "port", "port to use on the LaserScanner");
         def->optional(properties.timelimit, "timelimit", "timelimit for communication");
         def->optional(properties.subscribeDatagram, "subscribeDatagram", "subscribe to Datagram in communication or not");
-        def->optional(properties.protocol, "protocol", "Either use ASCII or Binary protocol")
-        .map(protocolToString(ScanProtocol::ASCII), ScanProtocol::ASCII)
-        .map(protocolToString(ScanProtocol::Binary), ScanProtocol::Binary);
-        def->optional(properties.sopasProtocolType, "sopasProtocolType", "Automatically set to true if the Scanner does not support ASCII communication");
         //Scanner parameters
         def->required(properties.scannerType, "scannerType", "Name of the LaserScanner");
         def->optional(properties.deviceNumber, "deviceNumber", "number of the LaserScanner Device");
@@ -153,8 +121,6 @@ namespace armarx
         def->optional(properties.rangeMin, "rangeMin", "minimum Range of the Scanner");
         def->optional(properties.rangeMax, "rangeMax", "maximum Range of the Scanner");
         def->optional(properties.timeIncrement, "timeIncrement", "timeIncrement??");
-        //Additional configuration
-        def->optional(properties.emulSensor, "emulateSensor", "overwrite the default Settings and don't connect to Scanner");
         return def;
     }
 
@@ -178,11 +144,6 @@ namespace armarx
         scanDevice.angleOffset = properties.angleOffset;
         scanDevice.timelimit = properties.timelimit;
         scanDevice.subscribeDatagram = properties.subscribeDatagram;
-        if (properties.newIpAddress != "")
-        {
-            scanDevice.changeIP = true;
-            scanDevice.newIpAddress = properties.newIpAddress;
-        }
         scanDevice.scannerType = properties.scannerType;
         scanDevice.deviceNumber = properties.deviceNumber;
         scanDevice.rangeMin = properties.rangeMin;
@@ -201,47 +162,10 @@ namespace armarx
             ARMARX_ERROR_S << "Could not create parser. Wrong Scanner name.";
             return;
         }
-        if (properties.emulSensor)
-        {
-            ARMARX_INFO_S << "Found paraemter emulSensor overwriting default settings. Emulation: True";
-            scanDevice.emulSensor = true;
-        }
-        switch (properties.protocol)
-        {
-            case ScanProtocol::ASCII:
-                if (scanDevice.parser->getCurrentParamPtr()->getNumberOfLayers() > 4)
-                {
-                    ARMARX_WARNING_S << "This scanner type does not support ASCII communication.\n"
-                                     << "Binary communication has been activated.\n"
-                                     << "The parameter \"sopasProtocolType\" has been set to \"true\".";
-                    scanDevice.sopasProtocolType = true;
-                    scanDevice.protocol = ScanProtocol::Binary;
-                }
-                else
-                {
-                    ARMARX_INFO_S << "ASCII protocol activated.";
-                    scanDevice.protocol = ScanProtocol::ASCII;
-                }
-                break;
-            case ScanProtocol::Binary:
-                ARMARX_INFO_S << "Binary protocol activated.";
-                scanDevice.protocol = ScanProtocol::Binary;
-                break;
-            default:
-                ARMARX_WARNING_S << "Unknown protocol type. Defaulting to Binary protocol.";
-                scanDevice.protocol = ScanProtocol::Binary;
-        }
+        scanDevice.parser->getCurrentParamPtr()->setUseBinaryProtocol(false);
+        scanDevice.colaDialectId = 'A';
+        ARMARX_INFO_S << "ASCII protocol activated.";
 
-        if (scanDevice.protocol == ScanProtocol::ASCII)
-        {
-            scanDevice.parser->getCurrentParamPtr()->setUseBinaryProtocol(false);
-            scanDevice.colaDialectId = 'A';
-        }
-        else
-        {
-            scanDevice.parser->getCurrentParamPtr()->setUseBinaryProtocol(true);
-            scanDevice.colaDialectId = 'B';
-        }
         ARMARX_INFO_S << "SickLaserUnit initialisation complete.";
     }
 
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
index e9a038959..4990eb80c 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h
@@ -34,7 +34,7 @@
 
 #include <vector>
 
-//#include "SickScanAdapter.h"
+#include "SickScanAdapter.h"
 #include <sick_scan/sick_scan_common.h>
 #include <sick_scan/sick_scan_common_tcp.h>
 #include <sick_scan/sick_generic_laser.h>
@@ -66,23 +66,18 @@ namespace armarx
         double timeIncrement;
         //communication parameters
         std::string ip;
-        std::string newIpAddress = "";
         std::string port;
         int timelimit = 5;
         bool subscribeDatagram = false;
-        ScanProtocol protocol = ScanProtocol::ASCII;
-        bool sopasProtocolType = false;
         bool useTcp = false;
-        bool changeIP = false;
-        bool emulSensor = false;
-        char colaDialectId = 'B';
+        char colaDialectId = 'A';
         //data and task pointers
         std::vector<long> scanData;
         RunState runState = RunState::scannerFinalize;
         RunningTask<SickLaserScanDevice>::pointer_type task;
         sick_scan::SickScanConfig cfg;
-        //SickScanAdapter* scanner;
-        sick_scan::SickScanCommonTcp* scanner;
+        SickScanAdapter* scanner;
+        //sick_scan::SickScanCommonTcp* scanner;
         sick_scan::SickGenericParser* parser;
         int result = sick_scan::ExitError;
         bool isSensorInitialized = false;
@@ -156,12 +151,9 @@ namespace armarx
         {
             //communication parameters
             std::string hostname = "192.168.8.133";
-            std::string newIpAddress = "";
             std::string port = "2112";
             int timelimit = 5;
             bool subscribeDatagram = false;
-            ScanProtocol protocol = ScanProtocol::ASCII;
-            bool sopasProtocolType = false;
             //scanner parameters
             std::string scannerType = "sick_tim_5xx";
             int deviceNumber = 0;
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
index 7bdb37dec..446676544 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.cpp
@@ -59,6 +59,17 @@
 #include <sick_scan/tcp/colaa.hpp>
 #include <sick_scan/tcp/colab.hpp>
 #include <sick_scan/sick_generic_radar.h>
+#include <sick_scan/helper/angle_compensator.h>
+#include <sick_scan/sick_scan_config_internal.h>
+#include <sick_scan/sick_generic_imu.h>
+
+#ifdef ROSSIMU
+#include <sick_scan/rosconsole_simu.hpp>
+#endif
+
+#include <sick_scan/binScanf.hpp>
+#include <sick_scan/RadarScan.h>
+#include <sick_scan/Encoder.h>
 
 #include <boost/asio.hpp>
 #include <boost/lambda/lambda.hpp>
@@ -67,11 +78,11 @@
 #include <boost/lexical_cast.hpp>
 #include <vector>
 
-#ifdef ROSSIMU
-
-#include <sick_scan/rosconsole_simu.hpp>
-
+#ifndef rad2deg
+#define rad2deg(x) ((x) / M_PI * 180.0)
 #endif
+#define deg2rad_const (0.017453292519943295769236907684886f)
+
 
 std::vector<unsigned char> exampleData(65536);
 std::vector<unsigned char> receivedData(65536);
@@ -91,155 +102,134 @@ namespace armarx
 {
     bool emulateReply(UINT8* requestData, int requestLen, std::vector<unsigned char>* replyVector)
     {
-        std::string request;
-        std::string reply;
-        std::vector<std::string> keyWordList;
-        std::vector<std::string> answerList;
-
-        std::string scannerType = "???";
-        ros::NodeHandle nhPriv;
-
-        enum
-        {
-            SIMU_RADAR = 0, SIMU_MRS_1XXX = 1, SIMU_NUM
-        };
-        int enumType = SIMU_RADAR; // Default simulation
-        if (true == nhPriv.getParam("scanner_type", scannerType))
-        {
-            if (scannerType.compare("sick_mrs_1xxx") == 0)
-            {
-                ROS_INFO("Simulate MRS1xxx");
-                enumType = SIMU_MRS_1XXX;
-            }
-        }
-
-        switch (enumType)
-        {
-            case SIMU_RADAR:
-
-                // XXX
-                keyWordList.push_back("sMN SetAccessMode");
-                answerList.push_back("sAN SetAccessMode 1");
-
-                keyWordList.push_back("sWN EIHstCola");
-                answerList.push_back("sWA EIHstCola");
-
-                keyWordList.push_back("sRN FirmwareVersion");
-                answerList.push_back("sRA FirmwareVersion 8 1.0.0.0R");
-
-                keyWordList.push_back("sRN OrdNum");
-                answerList.push_back("sRA OrdNum 7 1234567");
-
-                keyWordList.push_back("sWN TransmitTargets 1");
-                answerList.push_back("sWA TransmitTargets");
-
-                keyWordList.push_back("sWN TransmitObjects 1");
-                answerList.push_back("sWA TransmitObjects");
-
-                keyWordList.push_back("sWN TCTrackingMode 0");
-                answerList.push_back("sWA TCTrackingMode");
-
-                keyWordList.push_back("sRN SCdevicestate");
-                answerList.push_back("sRA SCdevicestate 1");
-
-                keyWordList.push_back("sRN DItype");
-                answerList.push_back("sRA DItype D RMS3xx-xxxxxx");
-
-                keyWordList.push_back("sRN ODoprh");
-                answerList.push_back("sRA ODoprh 451");
-
-                keyWordList.push_back("sMN mSCloadappdef");
-                answerList.push_back("sAN mSCloadappdef");
-
-
-                keyWordList.push_back("sRN SerialNumber");
-                answerList.push_back("sRA SerialNumber 8 18020073");
-
-                keyWordList.push_back("sMN Run");
-                answerList.push_back("sAN Run 1s");
-
-                keyWordList.push_back("sRN ODpwrc");
-                answerList.push_back("sRA ODpwrc 20");
-
-                keyWordList.push_back("sRN LocationName");
-                answerList.push_back("sRA LocationName B not defined");
-
-                keyWordList.push_back("sEN LMDradardata 1");
-                answerList.push_back("sEA LMDradardata 1");
-
-                for (int i = 0; i < requestLen; i++)
-                {
-                    request += (char) requestData[i];
-                }
-                for (size_t i = 0; i < keyWordList.size(); i++)
-                {
-                    if (request.find(keyWordList[i]) != std::string::npos)
-                    {
-                        reply = (char) 0x02;
-                        reply += answerList[i];
-                        reply += (char) 0x03;
-                    }
-                }
-
-                replyVector->clear();
-                for (size_t i = 0; i < reply.length(); i++)
-                {
-                    replyVector->push_back((unsigned char) reply[i]);
-                }
-                break;
-            case SIMU_MRS_1XXX:
-                ROS_INFO("Emulation of MRS_1xxx is not implemented.\n");
-                assert(0);
-                // XXX
-                break;
-        }
-
-
-        return (true);
+	std::string request;
+	std::string reply;
+	std::vector<std::string> keyWordList;
+	std::vector<std::string> answerList;
+
+	std::string scannerType = "???";
+	ros::NodeHandle nhPriv;
+
+	enum
+	{
+	    SIMU_RADAR = 0, SIMU_MRS_1XXX = 1, SIMU_NUM
+	};
+	// XXX
+	keyWordList.push_back("sMN SetAccessMode");
+	answerList.push_back("sAN SetAccessMode 1");
+
+	keyWordList.push_back("sWN EIHstCola");
+	answerList.push_back("sWA EIHstCola");
+
+	keyWordList.push_back("sRN FirmwareVersion");
+	answerList.push_back("sRA FirmwareVersion 8 1.0.0.0R");
+
+	keyWordList.push_back("sRN OrdNum");
+	answerList.push_back("sRA OrdNum 7 1234567");
+
+	keyWordList.push_back("sWN TransmitTargets 1");
+	answerList.push_back("sWA TransmitTargets");
+
+	keyWordList.push_back("sWN TransmitObjects 1");
+	answerList.push_back("sWA TransmitObjects");
+
+	keyWordList.push_back("sWN TCTrackingMode 0");
+	answerList.push_back("sWA TCTrackingMode");
+
+	keyWordList.push_back("sRN SCdevicestate");
+	answerList.push_back("sRA SCdevicestate 1");
+
+	keyWordList.push_back("sRN DItype");
+	answerList.push_back("sRA DItype D RMS3xx-xxxxxx");
+
+	keyWordList.push_back("sRN ODoprh");
+	answerList.push_back("sRA ODoprh 451");
+
+	keyWordList.push_back("sMN mSCloadappdef");
+	answerList.push_back("sAN mSCloadappdef");
+
+
+	keyWordList.push_back("sRN SerialNumber");
+	answerList.push_back("sRA SerialNumber 8 18020073");
+
+	keyWordList.push_back("sMN Run");
+	answerList.push_back("sAN Run 1s");
+
+	keyWordList.push_back("sRN ODpwrc");
+	answerList.push_back("sRA ODpwrc 20");
+
+	keyWordList.push_back("sRN LocationName");
+	answerList.push_back("sRA LocationName B not defined");
+
+	keyWordList.push_back("sEN LMDradardata 1");
+	answerList.push_back("sEA LMDradardata 1");
+
+	for (int i = 0; i < requestLen; i++)
+	{
+	    request += (char) requestData[i];
+	}
+	for (size_t i = 0; i < keyWordList.size(); i++)
+	{
+	    if (request.find(keyWordList[i]) != std::string::npos)
+	    {
+		reply = (char) 0x02;
+		reply += answerList[i];
+		reply += (char) 0x03;
+	    }
+	}
+
+	replyVector->clear();
+	for (size_t i = 0; i < reply.length(); i++)
+	{
+	    replyVector->push_back((unsigned char) reply[i]);
+	}
+
+	return (true);
     }
 
 
     SickScanAdapter::SickScanAdapter(const std::string& hostname, const std::string& port, int& timelimit,
-                                     sick_scan::SickGenericParser* parser, char cola_dialect_id)
-        :
-        sick_scan::SickScanCommon(parser),
-        socket_(io_service_),
-        deadline_(io_service_),
-        hostname_(hostname),
-        port_(port),
-        timelimit_(timelimit)
+				     sick_scan::SickGenericParser* parser, char cola_dialect_id)
+	:
+	sick_scan::SickScanCommon(parser),
+	socket_(io_service_),
+	deadline_(io_service_),
+	parser_ptr(parser),
+	hostname_(hostname),
+	port_(port),
+	timelimit_(timelimit)
     {
 
-        setEmulSensor(false);
-        if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
-        {
-            this->setProtocolType(CoLa_A);
-        }
+	setEmulSensor(false);
+	if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
+	{
+	    this->setProtocolType(CoLa_A);
+	}
 
-        if ((cola_dialect_id == 'b') || (cola_dialect_id == 'B'))
-        {
-            this->setProtocolType(CoLa_B);
-        }
+	if ((cola_dialect_id == 'b') || (cola_dialect_id == 'B'))
+	{
+	    this->setProtocolType(CoLa_B);
+	}
 
-        assert(this->getProtocolType() != CoLa_Unknown);
+	assert(this->getProtocolType() != CoLa_Unknown);
 
-        m_numberOfBytesInReceiveBuffer = 0;
-        m_alreadyReceivedBytes = 0;
-        this->setReplyMode(0);
-        // io_service_.setReadCallbackFunction(boost::bind(&SopasDevice::readCallbackFunction, this, _1, _2));
+	m_numberOfBytesInReceiveBuffer = 0;
+	m_alreadyReceivedBytes = 0;
+	this->setReplyMode(0);
+	// io_service_.setReadCallbackFunction(boost::bind(&SopasDevice::readCallbackFunction, this, _1, _2));
 
-        // Set up the deadline actor to implement timeouts.
-        // Based on blocking TCP example on:
-        // http://www.boost.org/doc/libs/1_46_0/doc/html/boost_asio/example/timeouts/blocking_tcp_client.cpp
-        deadline_.expires_at(boost::posix_time::pos_infin);
-        checkDeadline();
+	// Set up the deadline actor to implement timeouts.
+	// Based on blocking TCP example on:
+	// http://www.boost.org/doc/libs/1_46_0/doc/html/boost_asio/example/timeouts/blocking_tcp_client.cpp
+	deadline_.expires_at(boost::posix_time::pos_infin);
+	checkDeadline();
 
     }
 
     SickScanAdapter::~SickScanAdapter()
     {
-        // stop_scanner();
-        close_device();
+	// stop_scanner();
+	close_device();
     }
 
     using boost::asio::ip::tcp;
@@ -253,1277 +243,1043 @@ namespace armarx
     */
     int SickScanAdapter::loopOnce()
     {
-        static int cnt = 0;
-        diagnostics_.update();
-
-        unsigned char receiveBuffer[65536];
-        int actual_length = 0;
-        static unsigned int iteration_count = 0;
-        bool useBinaryProtocol = this->parser_->getCurrentParamPtr()->getUseBinaryProtocol();
-
-        ros::Time recvTimeStamp = ros::Time::now();  // timestamp incoming package, will be overwritten by get_datagram
-        // tcp packet
-        ros::Time recvTimeStampPush = ros::Time::now();  // timestamp
-
-        /*
-         * Try to get datagram
-         *
-         *
-         */
-
-
-        int packetsInLoop = 0;
-
-        const int maxNumAllowedPacketsToProcess = 25; // maximum number of packets, which will be processed in this loop.
-
-        int numPacketsProcessed = 0; // count number of processed datagrams
-
-        static bool firstTimeCalled = true;
-        static bool dumpData = false;
-        static int verboseLevel = 0;
-        static bool slamBundle = false;
-        float timeIncrement;
-        static std::string echoForSlam = "";
-        if (firstTimeCalled == true)
-        {
-
-            /* Dump Binary Protocol */
-            ros::NodeHandle tmpParam("~");
-            tmpParam.getParam("slam_echo", echoForSlam);
-            tmpParam.getParam("slam_bundle", slamBundle);
-            tmpParam.getParam("verboseLevel", verboseLevel);
-            firstTimeCalled = false;
-        }
-        do
-        {
-
-            int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop);
-            numPacketsProcessed++;
-
-            ros::Duration dur = recvTimeStampPush - recvTimeStamp;
-
-            if (result != 0)
-            {
-                ROS_ERROR("Read Error when getting datagram: %i.", result);
-                diagnostics_.broadcast(getDiagnosticErrorCode(), "Read Error when getting datagram.");
-                return sick_scan::ExitError; // return failure to exit node
-            }
-            if (actual_length <= 0)
-            {
-                return sick_scan::ExitSuccess;
-            } // return success to continue looping
-
-            // ----- if requested, skip frames
-            if (iteration_count++ % (config_.skip + 1) != 0)
-            {
-                return sick_scan::ExitSuccess;
-            }
-
-            if (publish_datagram_)
-            {
-                std_msgs::String datagram_msg;
-                datagram_msg.data = std::string(reinterpret_cast<char*>(receiveBuffer));
-                datagram_pub_.publish(datagram_msg);
-            }
-
-
-            if (verboseLevel > 0)
-            {
-                dumpDatagramForDebugging(receiveBuffer, actual_length);
-            }
-
-
-            bool deviceIsRadar = false;
-
-            if (this->parser_->getCurrentParamPtr()->getDeviceIsRadar() == true)
-            {
-                deviceIsRadar = true;
-            }
-
-            if (true == deviceIsRadar)
-            {
-                int errorCode = sick_scan::ExitSuccess;
+	ARMARX_INFO_S << "myLoop.";
+	static int cnt = 0;
+	diagnostics_.update();
+
+	unsigned char receiveBuffer[65536];
+	int actual_length = 0;
+	static unsigned int iteration_count = 0;
+	bool useBinaryProtocol = this->parser_ptr->getCurrentParamPtr()->getUseBinaryProtocol();
+
+	ros::Time recvTimeStamp = ros::Time::now();  // timestamp incoming package, will be overwritten by get_datagram
+	// tcp packet
+	ros::Time recvTimeStampPush = ros::Time::now();  // timestamp
+
+	/*
+	 * Try to get datagram
+	 *
+	 *
+	 */
+
+
+	int packetsInLoop = 0;
+
+	const int maxNumAllowedPacketsToProcess = 25; // maximum number of packets, which will be processed in this loop.
+
+	int numPacketsProcessed = 0; // count number of processed datagrams
+
+	static bool firstTimeCalled = true;
+	static bool dumpData = false;
+	static int verboseLevel = 0;
+	static bool slamBundle = false;
+	float timeIncrement;
+	static std::string echoForSlam = "";
+	if (firstTimeCalled == true)
+	{
+
+	    /* Dump Binary Protocol */
+	    ros::NodeHandle tmpParam("~");
+	    tmpParam.getParam("slam_echo", echoForSlam);
+	    tmpParam.getParam("slam_bundle", slamBundle);
+	    tmpParam.getParam("verboseLevel", verboseLevel);
+	    firstTimeCalled = false;
+	}
+	do
+	{
+
+	    int result = get_datagram(recvTimeStamp, receiveBuffer, 65536, &actual_length, useBinaryProtocol, &packetsInLoop);
+	    numPacketsProcessed++;
+
+	    ros::Duration dur = recvTimeStampPush - recvTimeStamp;
+
+	    if (result != 0)
+	    {
+		ROS_ERROR("Read Error when getting datagram: %i.", result);
+		diagnostics_.broadcast(getDiagnosticErrorCode(), "Read Error when getting datagram.");
+		return sick_scan::ExitError; // return failure to exit node
+	    }
+	    if (actual_length <= 0)
+	    {
+		return sick_scan::ExitSuccess;
+	    } // return success to continue looping
+
+	    // ----- if requested, skip frames
+	    if (iteration_count++ % (config_.skip + 1) != 0)
+	    {
+		return sick_scan::ExitSuccess;
+	    }
+
+	    //      if (publish_datagram_)
+	    //      {
+	    //      std_msgs::String datagram_msg;
+	    //      datagram_msg.data = std::string(reinterpret_cast<char*>(receiveBuffer));
+	    //      datagram_pub_.publish(datagram_msg);
+	    //      }
+
+
+	    if (verboseLevel > 0)
+	    {
+		dumpDatagramForDebugging(receiveBuffer, actual_length);
+	    }
+
+
+	    bool deviceIsRadar = false;
+
+	    if (this->parser_ptr->getCurrentParamPtr()->getDeviceIsRadar() == true)
+	    {
+		deviceIsRadar = true;
+	    }
+
+	    if (true == deviceIsRadar)
+	    {
+		int errorCode = sick_scan::ExitSuccess;
 #ifndef ROSSIMU
-                SickScanRadarSingleton* radar = SickScanRadarSingleton::getInstance();
-                // parse radar telegram and send pointcloud2-debug messages
-                errorCode = radar->parseDatagram(recvTimeStamp, (unsigned char*) receiveBuffer, actual_length,
-                                                 useBinaryProtocol);
+		SickScanRadarSingleton* radar = SickScanRadarSingleton::getInstance();
+		// parse radar telegram and send pointcloud2-debug messages
+		errorCode = radar->parseDatagram(recvTimeStamp, (unsigned char*) receiveBuffer, actual_length,
+						 useBinaryProtocol);
+#endif
+		return errorCode; // return success to continue looping
+	    }
+
+	    static sick_scan::SickScanImu scanImu(this); // todo remove static
+	    if (scanImu.isImuDatagram((char*) receiveBuffer, actual_length))
+	    {
+		ARMARX_INFO_S << "myLoop1 if.";
+		int errorCode = sick_scan::ExitSuccess;
+		if (scanImu.isImuAckDatagram((char*) receiveBuffer, actual_length))
+		{
+
+		}
+		else
+		{
+		    // parse radar telegram and send pointcloud2-debug messages
+		    errorCode = scanImu.parseDatagram(recvTimeStamp, (unsigned char*) receiveBuffer, actual_length,
+						      useBinaryProtocol);
+
+		}
+		return errorCode; // return success to continue looping
+
+
+	    }
+	    else
+	    {
+		ARMARX_INFO_S << "myLoop1 else.";
+		sensor_msgs::LaserScan msg;
+#ifndef _MSC_VER
+		sick_scan::Encoder EncoderMsg;
+		EncoderMsg.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
+		//TODO remove this hardcoded variable
+		bool FireEncoder = false;
+		EncoderMsg.header.frame_id = "Encoder";
+		EncoderMsg.header.seq = numPacketsProcessed;
+#endif
+		msg.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
+		double elevationAngleInRad = 0.0;
+		/*
+		 * datagrams are enclosed in <STX> (0x02), <ETX> (0x03) pairs
+		 */
+		char* buffer_pos = (char*) receiveBuffer;
+		char* dstart, *dend;
+		bool dumpDbg = false;
+		bool dataToProcess = true;
+		std::vector<float> vang_vec;
+		vang_vec.clear();
+		dstart = NULL;
+		dend = NULL;
+
+		while (dataToProcess)
+		{
+		    ARMARX_INFO_S << "myLoop2 dataProcess.";
+
+		    const int maxAllowedEchos = 5;
+
+		    uint numValidEchos = 0;
+		    int aiValidEchoIdx[maxAllowedEchos] = {0};
+		    size_t dlength;
+		    int success = -1;
+		    int numEchos = 0;
+		    int echoMask = 0;
+		    bool publishPointCloud = true;
+
+
+		    // Always Parsing Ascii-Encoding of datagram
+		    ARMARX_INFO_S << "myLoop3 ASCII.";
+		    dstart = strchr(buffer_pos, 0x02);
+		    if (dstart != NULL)
+		    {
+			dend = strchr(dstart + 1, 0x03);
+		    }
+		    if ((dstart != NULL) && (dend != NULL))
+		    {
+			dataToProcess = true; // continue parasing
+			dlength = dend - dstart;
+			*dend = '\0';
+			dstart++;
+		    }
+		    else
+		    {
+			dataToProcess = false;
+			break; //
+		    }
+
+		    if (dumpDbg)
+		    {
+			{
+			    static int cnt = 0;
+			    char szFileName[255];
+			    sprintf(szFileName, "/tmp/dump%05d.txt", cnt);
+			    cnt++;
+			}
+		    }
+
+		    // HEADER of data followed by DIST1 ... DIST2 ... DIST3 .... RSSI1 ... RSSI2.... RSSI3...
+
+		    // <frameid>_<sign>00500_DIST[1|2|3]
+		    numEchos = 1;
+		    // numEchos contains number of echos (1..5)
+		    // _msg holds ALL data of all echos
+
+		    ARMARX_INFO_S << "myLoop trying to parse...";
+		    success = parser_ptr->parse_datagram(dstart, dlength, config_, msg, numEchos, echoMask);
+		    publishPointCloud = true; // for MRS1000
+
+		    numValidEchos = 0;
+		    for (int i = 0; i < maxAllowedEchos; i++)
+		    {
+			aiValidEchoIdx[i] = 0;
+		    }
+
+
+
+		    int numOfLayers = parser_ptr->getCurrentParamPtr()->getNumberOfLayers();
+
+		    ARMARX_INFO_S << "numOfLayers: " << numOfLayers;
+
+		    if (success == sick_scan::ExitSuccess)
+		    {
+			ARMARX_INFO_S << "myLoop datagram parsed successfully.";
+
+			bool elevationPreCalculated = false;
+			double elevationAngleDegree = 0.0;
+
+			std::vector<float> rangeTmp = msg.ranges;  // copy all range value
+			std::vector<float> intensityTmp = msg.intensities; // copy all intensity value
+
+			int intensityTmpNum = intensityTmp.size();
+			float* intensityTmpPtr = NULL;
+			if (intensityTmpNum > 0)
+			{
+			    intensityTmpPtr = &intensityTmp[0];
+			}
+
+			// Helpful: https://answers.ros.org/question/191265/pointcloud2-access-data/
+			// https://gist.github.com/yuma-m/b5dcce1b515335c93ce8
+			// Copy to pointcloud
+			int layer = 0;
+			int baseLayer = 0;
+			bool useGivenElevationAngle = false;
+			switch (numOfLayers)
+			{
+			    case 1: // TIM571 etc.
+				baseLayer = 0;
+				break;
+			    case 4:
+
+				baseLayer = -1;
+				if (msg.header.seq == 250)
+				{
+				    layer = -1;
+				}
+				else if (msg.header.seq == 0)
+				{
+				    layer = 0;
+				}
+				else if ((int) msg.header.seq == -250)
+				{
+				    layer = 1;
+				}
+				else if ((int) msg.header.seq == -500)
+				{
+				    layer = 2;
+				}
+				elevationAngleDegree = this->parser_ptr->getCurrentParamPtr()->getElevationDegreeResolution();
+				elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
+				// 0.0436332 /*2.5 degrees*/;
+				break;
+			    case 24: // Preparation for MRS6000
+				baseLayer = -1;
+				layer = (msg.header.seq - (-2638)) / 125;
+				layer = (23 - layer) - 1;
+#if 0
+				elevationAngleDegree = this->parser_ptr->getCurrentParamPtr()->getElevationDegreeResolution();
+				elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
 #endif
-                return errorCode; // return success to continue looping
-            }
-
-            static SickScanImu scanImu(this); // todo remove static
-            if (scanImu.isImuDatagram((char*) receiveBuffer, actual_length))
-            {
-                int errorCode = sick_scan::ExitSuccess;
-                if (scanImu.isImuAckDatagram((char*) receiveBuffer, actual_length))
-                {
 
-                }
-                else
-                {
-                    // parse radar telegram and send pointcloud2-debug messages
-                    errorCode = scanImu.parseDatagram(recvTimeStamp, (unsigned char*) receiveBuffer, actual_length,
-                                                      useBinaryProtocol);
+				elevationPreCalculated = true;
+				if (vang_vec.size() > 0)
+				{
+				    useGivenElevationAngle = true;
+				}
+				break;
+			    default:
+				assert(0);
+				break; // unsupported
+
+			}
+
+
+
+
+
+			// XXX  - HIER MEHRERE SCANS publish, falls Mehrzielszenario läuft
+			if (numEchos > 5)
+			{
+			    ARMARX_WARNING_S << "Too many echos";
+			}
+			else
+			{
+
+			    size_t startOffset = 0;
+			    size_t endOffset = 0;
+			    int echoPartNum = msg.ranges.size() / numEchos;
+			    for (int i = 0; i < numEchos; i++)
+			    {
+
+				bool sendMsg = false;
+				if ((echoMask & (1 << i)) & 1 /*for TIM5xx outputChannelFlagId == 1*/)
+				{
+				    aiValidEchoIdx[numValidEchos] = i; // save index
+				    numValidEchos++;
+				    sendMsg = true;
+				}
+				startOffset = i * echoPartNum;
+				endOffset = (i + 1) * echoPartNum;
+
+				msg.ranges.clear();
+				msg.intensities.clear();
+				msg.ranges = std::vector<float>(
+						 rangeTmp.begin() + startOffset,
+						 rangeTmp.begin() + endOffset);
+				// check also for MRS1104
+				if (endOffset <= intensityTmp.size() && (intensityTmp.size() > 0))
+				{
+				    msg.intensities = std::vector<float>(
+							  intensityTmp.begin() + startOffset,
+							  intensityTmp.begin() + endOffset);
+				}
+				else
+				{
+				    msg.intensities.resize(echoPartNum); // fill with zeros
+				}
+				{
+				    // numEchos
+				    char szTmp[255] = {0};
+				    if (this->parser_ptr->getCurrentParamPtr()->getNumberOfLayers() > 1)
+				    {
+					const char* cpFrameId = config_.frame_id.c_str();
+					char szSignName[10] = {0};
+					if ((int) msg.header.seq < 0)
+					{
+					    strcpy(szSignName, "NEG");
+					}
+					else
+					{
+					    strcpy(szSignName, "POS");
+
+					}
+
+					sprintf(szTmp, "%s_%s_%03d_DIST%d", cpFrameId, szSignName, abs((int) msg.header.seq), i + 1);
+				    }
+				    else
+				    {
+					strcpy(szTmp, config_.frame_id.c_str());
+				    }
+
+				    msg.header.frame_id = std::string(szTmp);
+				    // Hector slam can only process ONE valid frame id.
+				    if (echoForSlam.length() > 0)
+				    {
+					if (slamBundle)
+					{
+					    // try to map first echos to horizontal layers.
+					    if (i == 0)
+					    {
+						// first echo
+						msg.header.frame_id = echoForSlam;
+						strcpy(szTmp, echoForSlam.c_str());  //
+						if (elevationAngleInRad != 0.0)
+						{
+						    float cosVal = cos(elevationAngleInRad);
+						    int rangeNum = msg.ranges.size();
+						    for (int j = 0; j < rangeNum; j++)
+						    {
+							msg.ranges[j] *= cosVal;
+						    }
+						}
+					    }
+					}
+
+					if (echoForSlam.compare(szTmp) == 0)
+					{
+					    sendMsg = true;
+					}
+					else
+					{
+					    sendMsg = false;
+					}
+				    }
+
+				}
+#ifndef _MSC_VER
+				if (parser_ptr->getCurrentParamPtr()->getEncoderMode() >= 0 && FireEncoder == true)//
+				{
+				    Encoder_pub.publish(EncoderMsg);
+				}
+				if (numOfLayers > 4)
+				{
+				    sendMsg = false; // too many layers for publish as scan message. Only pointcloud messages will be pub.
+				}
+
+				//for TIM5xx outputChannelFlagId == 1
+				if (sendMsg & 1)  // publish only configured channels - workaround for cfg-bug MRS1104
+				{
+				    //TODO: publish in armarx
+				    //pub_.publish(msg);
+				}
+#else
+				printf("MSG received...");
+#endif
+			    }
+			}
+
+
+			if (publishPointCloud == true)
+			{
+
+
+			    const int numChannels = 4; // x y z i (for intensity)
+
+			    int numTmpLayer = numOfLayers;
+
+
+			    cloud_.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
+
+
+			    cloud_.header.frame_id = config_.frame_id;
+			    cloud_.header.seq = 0;
+			    cloud_.height = numTmpLayer * numValidEchos; // due to multi echo multiplied by num. of layers
+			    cloud_.width = msg.ranges.size();
+			    cloud_.is_bigendian = false;
+			    cloud_.is_dense = true;
+			    cloud_.point_step = numChannels * sizeof(float);
+			    cloud_.row_step = cloud_.point_step * cloud_.width;
+			    cloud_.fields.resize(numChannels);
+			    for (int i = 0; i < numChannels; i++)
+			    {
+				std::string channelId[] = {"x", "y", "z", "intensity"};
+				cloud_.fields[i].name = channelId[i];
+				cloud_.fields[i].offset = i * sizeof(float);
+				cloud_.fields[i].count = 1;
+				cloud_.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
+			    }
+
+			    cloud_.data.resize(cloud_.row_step * cloud_.height);
+
+			    unsigned char* cloudDataPtr = &(cloud_.data[0]);
+
+
+			    // prepare lookup for elevation angle table
+
+			    std::vector<float> cosAlphaTable; // Lookup table for cos
+			    std::vector<float> sinAlphaTable; // Lookup table for sin
+			    size_t rangeNum = rangeTmp.size() / numValidEchos;
+			    cosAlphaTable.resize(rangeNum);
+			    sinAlphaTable.resize(rangeNum);
+			    float mirror_factor = 1.0;
+			    float angleShift = 0;
+			    if (this->parser_ptr->getCurrentParamPtr()->getScanMirroredAndShifted())
+			    {
+				//                mirror_factor = -1.0;
+				//                angleShift = +M_PI/2.0; // add 90 deg for NAV3xx-series
+			    }
+
+			    for (size_t iEcho = 0; iEcho < numValidEchos; iEcho++)
+			    {
+
+				float angle = config_.min_ang;
+
+
+				float* cosAlphaTablePtr = &cosAlphaTable[0];
+				float* sinAlphaTablePtr = &sinAlphaTable[0];
+
+				float* vangPtr = NULL;
+				float* rangeTmpPtr = &rangeTmp[0];
+				if (vang_vec.size() > 0)
+				{
+				    vangPtr = &vang_vec[0];
+				}
+				for (size_t i = 0; i < rangeNum; i++)
+				{
+				    enum enum_index_descr
+				    {
+					idx_x,
+					idx_y,
+					idx_z,
+					idx_intensity,
+					idx_num
+				    };
+				    long adroff = i * (numChannels * (int) sizeof(float));
+
+				    adroff += (layer - baseLayer) * cloud_.row_step;
+
+				    adroff += iEcho * cloud_.row_step * numTmpLayer;
+
+				    unsigned char* ptr = cloudDataPtr + adroff;
+				    float* fptr = (float*)(cloudDataPtr + adroff);
+
+				    geometry_msgs::Point32 point;
+				    float range_meter = rangeTmpPtr[iEcho * rangeNum + i];
+				    float phi = angle; // azimuth angle
+				    float alpha = 0.0;  // elevation angle
+
+				    if (useGivenElevationAngle) // FOR MRS6124
+				    {
+					alpha = -vangPtr[i] * deg2rad_const;
+				    }
+				    else
+				    {
+					if (elevationPreCalculated) // FOR MRS6124 without VANGL
+					{
+					    alpha = elevationAngleInRad;
+					}
+					else
+					{
+					    alpha = layer * elevationAngleDegree; // for MRS1104
+					}
+				    }
+
+				    if (iEcho == 0)
+				    {
+					cosAlphaTablePtr[i] = cos(alpha); // for z-value (elevation)
+					sinAlphaTablePtr[i] = sin(alpha);
+				    }
+				    else
+				    {
+					// Just for Debugging: printf("%3d %8.3lf %8.3lf\n", (int)i, cosAlphaTablePtr[i], sinAlphaTablePtr[i]);
+				    }
+				    // Thanks to Sebastian Pütz <spuetz@uos.de> for his hint
+				    float rangeCos = range_meter * cosAlphaTablePtr[i];
+
+				    double phi_used = phi  + angleShift;
+				    //TODO Angle Compensation?
+				    //                                    if (this->angleCompensator != NULL)
+				    //                                    {
+				    //                                        phi_used = angleCompensator->compensateAngleInRadFromRos(phi_used);
+				    //                                    }
+				    fptr[idx_x] = rangeCos * cos(phi_used);  // copy x value in pointcloud
+				    fptr[idx_y] = rangeCos * sin(phi_used);  // copy y value in pointcloud
+				    fptr[idx_z] = range_meter * sinAlphaTablePtr[i] * mirror_factor;// copy z value in pointcloud
+
+				    fptr[idx_intensity] = 0.0;
+				    if (config_.intensity)
+				    {
+					int intensityIndex = aiValidEchoIdx[iEcho] * rangeNum + i;
+					// intensity values available??
+					if (intensityIndex < intensityTmpNum)
+					{
+					    fptr[idx_intensity] = intensityTmpPtr[intensityIndex]; // copy intensity value in pointcloud
+					}
+				    }
+				    angle += msg.angle_increment;
+				}
+				// Publish
+				static int cnt = 0;
+				int layerOff = (layer - baseLayer);
+
+			    }
+			    // if ( (msg.header.seq == 0) || (layerOff == 0)) // FIXEN!!!!
+			    bool shallIFire = false;
+			    if ((msg.header.seq == 0) || (msg.header.seq == 237))
+			    {
+				shallIFire = true;
+			    }
+
+
+			    static int layerCnt = 0;
+			    static int layerSeq[4];
+
+			    if (config_.cloud_output_mode > 0)
+			    {
+
+				layerSeq[layerCnt % 4] = layer;
+				if (layerCnt >= 4)  // mind. erst einmal vier Layer zusammensuchen
+				{
+				    shallIFire = true; // here are at least 4 layers available
+				}
+				else
+				{
+				    shallIFire = false;
+				}
+
+				layerCnt++;
+			    }
+
+			    if (shallIFire) // shall i fire the signal???
+			    {
+#ifdef ROSSIMU
+				static int cnt = 0;
+				cnt++;
 
-                }
-                return errorCode; // return success to continue looping
+				printf("PUBLISH_DATA:\n");
 
+				unsigned char* cloudDataPtr = &(cloud_.data[0]);
+				int w = cloud_.width;
+				int h = cloud_.height;
 
-            }
-            else
-            {
+				int numShots = w * h;
 
-                sensor_msgs::LaserScan msg;
-#ifndef _MSC_VER
-                sick_scan::Encoder EncoderMsg;
-                EncoderMsg.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
-                //TODO remove this hardcoded variable
-                bool FireEncoder = false;
-                EncoderMsg.header.frame_id = "Encoder";
-                EncoderMsg.header.seq = numPacketsProcessed;
-#endif
-                msg.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
-                double elevationAngleInRad = 0.0;
-                /*
-                 * datagrams are enclosed in <STX> (0x02), <ETX> (0x03) pairs
-                 */
-                char* buffer_pos = (char*) receiveBuffer;
-                char* dstart, *dend;
-                bool dumpDbg = false;
-                bool dataToProcess = true;
-                std::vector<float> vang_vec;
-                vang_vec.clear();
-                dstart = NULL;
-                dend = NULL;
-
-                while (dataToProcess)
-                {
-                    const int maxAllowedEchos = 5;
-
-                    int numValidEchos = 0;
-                    int aiValidEchoIdx[maxAllowedEchos] = {0};
-                    size_t dlength;
-                    int success = -1;
-                    int numEchos = 0;
-                    int echoMask = 0;
-                    bool publishPointCloud = true;
-
-                    if (useBinaryProtocol)
-                    {
-                        // if binary protocol used then parse binary message
-                        std::vector<unsigned char> receiveBufferVec = std::vector<unsigned char>(receiveBuffer,
-                                receiveBuffer + actual_length);
-#ifdef DEBUG_DUMP_TO_CONSOLE_ENABLED
-                        if (actual_length > 1000)
-                        {
-                            DataDumper::instance().dumpUcharBufferToConsole(receiveBuffer, actual_length);
-
-                        }
-
-                        DataDumper::instance().dumpUcharBufferToConsole(receiveBuffer, actual_length);
-#endif
-                        if (receiveBufferVec.size() > 8)
-                        {
-                            long idVal = 0;
-                            long lenVal = 0;
-                            memcpy(&idVal, receiveBuffer + 0, 4);  // read identifier
-                            memcpy(&lenVal, receiveBuffer + 4, 4);  // read length indicator
-                            swap_endian((unsigned char*) &lenVal, 4);
-
-                            if (idVal == 0x02020202)  // id for binary message
-                            {
-#if  0
-                                {
-                                    static int cnt = 0;
-                                    char szFileName[255];
+				float* ptr = (float*) cloudDataPtr;
 
-#ifdef _MSC_VER
-                                    sprintf(szFileName, "c:\\temp\\dump%05d.bin", cnt);
+				if (cnt == 25)
+				{
+				    char jpgFileName_tmp[255] = { 0 };
+#if linux
+				    strcpy(jpgFileName_tmp, "./demo/scan.jpg_tmp");
 #else
-                                    sprintf(szFileName, "/tmp/dump%05d.txt", cnt);
+				    strcpy(jpgFileName_tmp, "..\\demo\\scan.jpg_tmp");
 #endif
-                                    FILE* fout;
-                                    fout = fopen(szFileName, "wb");
-                                    fwrite(receiveBuffer, actual_length, 1, fout);
-                                    fclose(fout);
-                                    cnt++;
-                                }
+				    int xic = 400;
+				    int yic = 400;
+				    int w2i = 400;
+				    int h2i = 400;
+				    int hi = h2i * 2 + 1;
+				    int wi = w2i * 2 + 1;
+				    int pixNum = hi * wi;
+				    int numColorChannel = 3;
+				    unsigned char* pixel = (unsigned char*) malloc(numColorChannel * hi * wi);
+				    memset(pixel, 0, numColorChannel * pixNum);
+				    double scaleFac = 50.0;
+
+				    for (int i = 0; i < hi; i++)
+				    {
+					int pixAdr = numColorChannel * (i * wi + xic);
+					pixel[pixAdr] = 0x40;
+					pixel[pixAdr + 1] = 0x40;
+					pixel[pixAdr + 2] = 0x40;
+				    }
+				    for (int i = 0; i < wi; i++)
+				    {
+					int pixAdr = numColorChannel * (yic * wi + i);
+					pixel[pixAdr] = 0x40;
+					pixel[pixAdr + 1] = 0x40;
+					pixel[pixAdr + 2] = 0x40;
+				    }
+
+				    scaleFac *= -1.0;
+				    for (int i = 0; i < numShots; i++)
+				    {
+					double x, y, z, intensity;
+					x = ptr[0];
+					y = ptr[1];
+					z = ptr[2];
+					intensity = ptr[3];
+					ptr += 4;
+					int xi = (x * scaleFac) + xic;
+					int yi = (y * scaleFac) + yic;
+					if ((xi >= 0) && (xi < wi))
+					{
+					    if ((yi >= 0) && (xi < hi))
+					    {
+						// yi shows left (due to neg. scaleFac)
+						// xi shows up (due to neg. scaleFac)
+						int pixAdr = numColorChannel * (xi * wi + yi);
+						int layer = i / w;
+						unsigned char color[3] = {0x00};
+						switch (layer)
+						{
+						    case 0:
+							color[0] = 0xFF;
+							break;
+						    case 1:
+							color[1] = 0xFF;
+							break;
+						    case 2:
+							color[2] = 0xFF;
+							break;
+						    case 3:
+							color[0] = 0xFF;
+							color[1] = 0xFF;
+							break;
+						}
+
+						for (int kk = 0; kk < 3; kk++)
+						{
+						    pixel[pixAdr + kk] = color[kk];
+
+						}
+					    }
+					}
+
+				    }
+
+				    // Write CSV-File
+				    char csvFileNameTmp[255];
+#if linux
+				    strcpy(csvFileNameTmp, "./demo/scan.csv_tmp");
 #endif
-                                // binary message
-                                if (lenVal < actual_length)
-                                {
-                                    short elevAngleX200 = 0;  // signed short (F5 B2  -> Layer 24
-                                    // F5B2h -> -2638/200= -13.19°
-                                    int scanFrequencyX100 = 0;
-                                    double elevAngle = 0.00;
-                                    double scanFrequency = 0.0;
-                                    long measurementFrequencyDiv100 = 0; // multiply with 100
-                                    int numOfEncoders = 0;
-                                    int numberOf16BitChannels = 0;
-                                    int numberOf8BitChannels = 0;
-                                    uint32_t SystemCountScan = 0;
-                                    static uint32_t lastSystemCountScan = 0;// this variable is used to ensure that only the first time stamp of an multi layer scann is used for PLL updating
-                                    uint32_t SystemCountTransmit = 0;
-
-                                    memcpy(&elevAngleX200, receiveBuffer + 50, 2);
-                                    swap_endian((unsigned char*) &elevAngleX200, 2);
-
-                                    elevationAngleInRad = -elevAngleX200 / 200.0 * deg2rad_const;
-                                    //TODO check this ??
-                                    msg.header.seq = elevAngleX200; // should be multiple of 0.625° starting with -2638 (corresponding to 13.19°)
-
-                                    memcpy(&SystemCountScan, receiveBuffer + 0x26, 4);
-                                    swap_endian((unsigned char*) &SystemCountScan, 4);
-
-                                    memcpy(&SystemCountTransmit, receiveBuffer + 0x2A, 4);
-                                    swap_endian((unsigned char*) &SystemCountTransmit, 4);
-                                    double timestampfloat = recvTimeStamp.sec + recvTimeStamp.nsec * 1e-9;
-                                    bool bRet;
-                                    if (SystemCountScan !=
-                                        lastSystemCountScan)//MRS 6000 sends 6 packets with same  SystemCountScan we should only update the pll once with this time stamp since the SystemCountTransmit are different and this will only increase jitter of the pll
-                                    {
-                                        bRet = SoftwarePLL::instance().updatePLL(recvTimeStamp.sec, recvTimeStamp.nsec,
-                                                SystemCountTransmit);
-                                        lastSystemCountScan = SystemCountScan;
-                                    }
-                                    ros::Time tmp_time = recvTimeStamp;
-                                    bRet = SoftwarePLL::instance().getCorrectedTimeStamp(recvTimeStamp.sec, recvTimeStamp.nsec,
-                                            SystemCountScan);
-                                    double timestampfloat_coor = recvTimeStamp.sec + recvTimeStamp.nsec * 1e-9;
-                                    double DeltaTime = timestampfloat - timestampfloat_coor;
-                                    //ROS_INFO("%F,%F,%u,%u,%F",timestampfloat,timestampfloat_coor,SystemCountTransmit,SystemCountScan,DeltaTime);
-                                    //TODO Handle return values
-                                    if (config_.sw_pll_only_publish == true && bRet == false)
-                                    {
-                                        int packets_expected_to_drop = SoftwarePLL::instance().fifoSize - 1;
-                                        SoftwarePLL::instance().packeds_droped++;
-                                        ROS_INFO("%i / %i Packet dropped Software PLL not yet locked.",
-                                                 SoftwarePLL::instance().packeds_droped, packets_expected_to_drop);
-                                        if (SoftwarePLL::instance().packeds_droped == packets_expected_to_drop)
-                                        {
-                                            ROS_INFO("Software PLL is expected to be ready now!");
-                                        }
-                                        if (SoftwarePLL::instance().packeds_droped > packets_expected_to_drop)
-                                        {
-                                            ROS_WARN("More packages than expected were dropped!!\n"
-                                                     "Check the network connection.\n"
-                                                     "Check if the system time has been changed in a leap.\n"
-                                                     "If the problems can persist, disable the software PLL with the option sw_pll_only_publish=False  !");
-                                        }
-                                        dataToProcess = false;
-                                        break;
-                                    }
-
-#ifdef DEBUG_DUMP_ENABLED
-                                    double elevationAngleInDeg = elevationAngleInRad = -elevAngleX200 / 200.0;
-                                    // DataDumper::instance().pushData((double)SystemCountScan, "LAYER", elevationAngleInDeg);
-                                    //DataDumper::instance().pushData((double)SystemCountScan, "LASESCANTIME", SystemCountScan);
-                                    //DataDumper::instance().pushData((double)SystemCountTransmit, "LASERTRANSMITTIME", SystemCountTransmit);
-                                    //DataDumper::instance().pushData((double)SystemCountScan, "LASERTRANSMITDELAY", debug_duration.toSec());
+				    FILE* foutCsv = fopen(csvFileNameTmp, "w");
+				    if (foutCsv)
+				    {
+					// ZIEL: fprintf(foutCsv,"timestamp;range;elevation;azimuth;x;y;z;intensity\n");
+					fprintf(foutCsv, "timestamp_sec;timestamp_nanosec;range;azimuth_deg;elevation_deg;x;y;z;intensity\n");
+					unsigned char* cloudDataPtr = &(cloud_.data[0]);
+
+					int numShots = w * h;
+
+					float* ptr = (float*) cloudDataPtr;
+
+
+					long timestamp_sec = cloud_.header.stamp.sec;
+					long timestamp_nanosec = cloud_.header.stamp.nsec;
+					for (int i = 0; i < numShots; i++)
+					{
+					    double x, y, z, intensity;
+					    x = ptr[0];
+					    y = ptr[1];
+					    z = ptr[2];
+					    float range_xy = sqrt(x * x + y * y);
+					    float range_xyz = sqrt(x * x + y * y + z * z);
+					    float elevation = atan2(z, range_xy);
+					    float azimuth = atan2(y, x);
+					    float elevationDeg = elevation * 180.0 / M_PI;
+					    float azimuthDeg = azimuth * 180.0 / M_PI;
+
+					    intensity = ptr[3];
+					    ptr += 4;
+					    fprintf(foutCsv, "%12ld;%12ld;%8.3lf;%8.3lf;%8.3lf;%8.3f;%8.3f;%8.3f;%8.0f\n", timestamp_sec, timestamp_nanosec, range_xyz, azimuthDeg, elevationDeg, x, y, z, intensity);
+					}
+					fclose(foutCsv);
+#ifdef linux
+					rename(csvFileNameTmp, "./demo/scan.csv");
+#else
+					_unlink("..\\demo\\scan.csv");
+					rename(csvFileNameTmp, "..\\demo\\scan.csv");
 #endif
+				    }
+				    else
+				    {
+					ARMARX_INFO_S << "PANIC: Can not open file for writing. Check existience of demo dir. or patch  code.";
+				    }
+				    cnt = 0;
+				}
 
-                                    memcpy(&scanFrequencyX100, receiveBuffer + 52, 4);
-                                    swap_endian((unsigned char*) &scanFrequencyX100, 4);
-
-                                    memcpy(&measurementFrequencyDiv100, receiveBuffer + 56, 4);
-                                    swap_endian((unsigned char*) &measurementFrequencyDiv100, 4);
+#else
+				if (config_.cloud_output_mode == 0)
+				{
+				    // standard handling of scans
+				    cloud_pub_.publish(cloud_);
 
+				}
 
-                                    msg.scan_time = 1.0 / (scanFrequencyX100 / 100.0);
+				//                cloud_pub_.publish(cloud_);
+#endif
+			    }
+			}
+		    }
+		    // Start Point
+		    if (dend != NULL)
+		    {
+			buffer_pos = dend + 1;
+		    }
+		} // end of while loop
+	    }
+
+	    // shall we process more data? I.e. are there more packets to process in the input queue???
+
+	}
+	while ((packetsInLoop > 0) && (numPacketsProcessed < maxNumAllowedPacketsToProcess));
+	return sick_scan::ExitSuccess; // return success to continue looping
+    }
 
-                                    //due firmware inconsistency
-                                    if (measurementFrequencyDiv100 > 10000)
-                                    {
-                                        measurementFrequencyDiv100 /= 100;
-                                    }
-                                    msg.time_increment = 1.0 / (measurementFrequencyDiv100 * 100.0);
-                                    timeIncrement = msg.time_increment;
-                                    msg.range_min = parser_->get_range_min();
-                                    msg.range_max = parser_->get_range_max();
+    /*
+    //Adapted from sick_generic_parser
+    int SickScanAdapter::parse_datagram(char* datagram, size_t datagram_length, sick_scan::SickScanConfig& config,
+    sensor_msgs::LaserScan& msg, int& numEchos, int& echoMask)
+    {
+    // echoMask introduced to get a workaround for cfg bug using MRS1104
+    ros::NodeHandle tmpParam("~");
+    bool dumpData = false;
+    int verboseLevel = 0;
+    tmpParam.getParam("verboseLevel", verboseLevel);
+
+    int HEADER_FIELDS = 32;
+    char* cur_field;
+    size_t count;
+    int scannerIdx = parser_ptr->lookUpForAllowedScanner(parser_ptr->getScannerType());
+
+    // Reserve sufficient space
+    std::vector<char*> fields;
+    fields.reserve(datagram_length / 2);
+
+    // ----- only for debug output
+    std::vector<char> datagram_copy_vec;
+    datagram_copy_vec.resize(datagram_length + 1); // to avoid using malloc. destructor frees allocated mem.
+    char* datagram_copy = &(datagram_copy_vec[0]);
+
+    if (verboseLevel > 0)
+    {
+    ARMARX_WARNING("Verbose LEVEL activated. Only for DEBUG.");
+    }
 
-                                    memcpy(&numOfEncoders, receiveBuffer + 60, 2);
-                                    swap_endian((unsigned char*) &numOfEncoders, 2);
-                                    int encoderDataOffset = 6 * numOfEncoders;
-                                    int32_t EncoderPosTicks[4] = {0};
-                                    int16_t EncoderSpeed[4] = {0};
+    if (verboseLevel > 0)
+    {
+    static int cnt = 0;
+    char szDumpFileName[511] = {0};
+    char szDir[255] = {0};
+    #ifdef _MSC_VER
+    strcpy(szDir, "C:\\temp\\");
+    #else
+    strcpy(szDir, "/tmp/");
+    #endif
+    sprintf(szDumpFileName, "%stmp%06d.bin", szDir, cnt);
+    bool isBinary = parser_ptr->getCurrentParamPtr()->getUseBinaryProtocol();
+    if (isBinary)
+    {
+    FILE* ftmp;
+    ftmp = fopen(szDumpFileName, "wb");
+    if (ftmp != NULL)
+    {
+    fwrite(datagram, datagram_length, 1, ftmp);
+    fclose(ftmp);
+    }
+    }
+    cnt++;
+    }
+    ARMARX_INFO("parse_datagram(): Copying");
+    strncpy(datagram_copy, datagram, datagram_length); // datagram will be changed by strtok
+    datagram_copy[datagram_length] = 0;
 
-#ifndef _MSC_VER
-                                    if (numOfEncoders > 0 && numOfEncoders < 5)
-                                    {
-                                        FireEncoder = true;
-                                        for (int EncoderNum = 0; EncoderNum < numOfEncoders; EncoderNum++)
-                                        {
-                                            memcpy(&EncoderPosTicks[EncoderNum], receiveBuffer + 62 + EncoderNum * 6, 4);
-                                            swap_endian((unsigned char*) &EncoderPosTicks[EncoderNum], 4);
-                                            memcpy(&EncoderSpeed[EncoderNum], receiveBuffer + 66 + EncoderNum * 6, 2);
-                                            swap_endian((unsigned char*) &EncoderSpeed[EncoderNum], 2);
-                                        }
-                                    }
-                                    //TODO handle multi encoder with multiple encode msg or different encoder msg definition now using only first encoder
-                                    EncoderMsg.enc_position = EncoderPosTicks[0];
-                                    EncoderMsg.enc_speed = EncoderSpeed[0];
-#endif
-                                    memcpy(&numberOf16BitChannels, receiveBuffer + 62 + encoderDataOffset, 2);
-                                    swap_endian((unsigned char*) &numberOf16BitChannels, 2);
-
-                                    int parseOff = 64 + encoderDataOffset;
-
-
-                                    char szChannel[255] = {0};
-                                    float scaleFactor = 1.0;
-                                    float scaleFactorOffset = 0.0;
-                                    int32_t startAngleDiv10000 = 1;
-                                    int32_t sizeOfSingleAngularStepDiv10000 = 1;
-                                    double startAngle = 0.0;
-                                    double sizeOfSingleAngularStep = 0.0;
-                                    short numberOfItems = 0;
-
-                                    static int cnt = 0;
-                                    cnt++;
-                                    // get number of 8 bit channels
-                                    // we must jump of the 16 bit data blocks including header ...
-                                    for (int i = 0; i < numberOf16BitChannels; i++)
-                                    {
-                                        int numberOfItems = 0x00;
-                                        memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
-                                        swap_endian((unsigned char*) &numberOfItems, 2);
-                                        parseOff += 21; // 21 Byte header followed by data entries
-                                        parseOff += numberOfItems * 2;
-                                    }
-
-                                    // now we can read the number of 8-Bit-Channels
-                                    memcpy(&numberOf8BitChannels, receiveBuffer + parseOff, 2);
-                                    swap_endian((unsigned char*) &numberOf8BitChannels, 2);
-
-                                    parseOff = 64 + encoderDataOffset;
-                                    enum datagram_parse_task
-                                    {
-                                        process_dist,
-                                        process_vang,
-                                        process_rssi,
-                                        process_idle
-                                    };
-                                    int rssiCnt = 0;
-                                    int vangleCnt = 0;
-                                    int distChannelCnt = 0;
-
-                                    for (int processLoop = 0; processLoop < 2; processLoop++)
-                                    {
-                                        int totalChannelCnt = 0;
-
-
-                                        bool bCont = true;
-
-                                        datagram_parse_task task = process_idle;
-                                        bool parsePacket = true;
-                                        parseOff = 64 + encoderDataOffset;
-                                        bool processData = false;
-
-                                        if (processLoop == 0)
-                                        {
-                                            distChannelCnt = 0;
-                                            rssiCnt = 0;
-                                            vangleCnt = 0;
-                                        }
-
-                                        if (processLoop == 1)
-                                        {
-                                            processData = true;
-                                            numEchos = distChannelCnt;
-                                            msg.ranges.resize(numberOfItems * numEchos);
-                                            if (rssiCnt > 0)
-                                            {
-                                                msg.intensities.resize(numberOfItems * rssiCnt);
-                                            }
-                                            else
-                                            {
-                                            }
-                                            if (vangleCnt > 0) // should be 0 or 1
-                                            {
-                                                vang_vec.resize(numberOfItems * vangleCnt);
-                                            }
-                                            else
-                                            {
-                                                vang_vec.clear();
-                                            }
-                                            echoMask = (1 << numEchos) - 1;
-
-                                            // reset count. We will use the counter for index calculation now.
-                                            distChannelCnt = 0;
-                                            rssiCnt = 0;
-                                            vangleCnt = 0;
-
-                                        }
-
-                                        szChannel[6] = '\0';
-                                        scaleFactor = 1.0;
-                                        scaleFactorOffset = 0.0;
-                                        startAngleDiv10000 = 1;
-                                        sizeOfSingleAngularStepDiv10000 = 1;
-                                        startAngle = 0.0;
-                                        sizeOfSingleAngularStep = 0.0;
-                                        numberOfItems = 0;
-
-
-#if 1 // prepared for multiecho parsing
-
-                                        bCont = true;
-                                        bool doVangVecProc = false;
-                                        // try to get number of DIST and RSSI from binary data
-                                        task = process_idle;
-                                        do
-                                        {
-                                            task = process_idle;
-                                            doVangVecProc = false;
-                                            int processDataLenValuesInBytes = 2;
-
-                                            if (totalChannelCnt == numberOf16BitChannels)
-                                            {
-                                                parseOff += 2; // jump of number of 8 bit channels- already parsed above
-                                            }
-
-                                            if (totalChannelCnt >= numberOf16BitChannels)
-                                            {
-                                                processDataLenValuesInBytes = 1; // then process 8 bit values ...
-                                            }
-                                            bCont = false;
-                                            strcpy(szChannel, "");
-
-                                            if (totalChannelCnt < (numberOf16BitChannels + numberOf8BitChannels))
-                                            {
-                                                szChannel[5] = '\0';
-                                                strncpy(szChannel, (const char*) receiveBuffer + parseOff, 5);
-                                            }
-                                            else
-                                            {
-                                                // all channels processed (16 bit and 8 bit channels)
-                                            }
-
-                                            if (strstr(szChannel, "DIST") == szChannel)
-                                            {
-                                                task = process_dist;
-                                                distChannelCnt++;
-                                                bCont = true;
-                                                numberOfItems = 0;
-                                                memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
-                                                swap_endian((unsigned char*) &numberOfItems, 2);
-
-                                            }
-                                            if (strstr(szChannel, "VANG") == szChannel)
-                                            {
-                                                vangleCnt++;
-                                                task = process_vang;
-                                                bCont = true;
-                                                numberOfItems = 0;
-                                                memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
-                                                swap_endian((unsigned char*) &numberOfItems, 2);
-
-                                                vang_vec.resize(numberOfItems);
-
-                                            }
-                                            if (strstr(szChannel, "RSSI") == szChannel)
-                                            {
-                                                task = process_rssi;
-                                                rssiCnt++;
-                                                bCont = true;
-                                                numberOfItems = 0;
-                                                // copy two byte value (unsigned short to  numberOfItems
-                                                memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
-                                                swap_endian((unsigned char*) &numberOfItems, 2);  // swap
-
-                                            }
-                                            if (bCont)
-                                            {
-                                                scaleFactor = 0.0;
-                                                scaleFactorOffset = 0.0;
-                                                startAngleDiv10000 = 0;
-                                                sizeOfSingleAngularStepDiv10000 = 0;
-                                                numberOfItems = 0;
-
-                                                memcpy(&scaleFactor, receiveBuffer + parseOff + 5, 4);
-                                                memcpy(&scaleFactorOffset, receiveBuffer + parseOff + 9, 4);
-                                                memcpy(&startAngleDiv10000, receiveBuffer + parseOff + 13, 4);
-                                                memcpy(&sizeOfSingleAngularStepDiv10000, receiveBuffer + parseOff + 17, 2);
-                                                memcpy(&numberOfItems, receiveBuffer + parseOff + 19, 2);
-
-
-                                                swap_endian((unsigned char*) &scaleFactor, 4);
-                                                swap_endian((unsigned char*) &scaleFactorOffset, 4);
-                                                swap_endian((unsigned char*) &startAngleDiv10000, 4);
-                                                swap_endian((unsigned char*) &sizeOfSingleAngularStepDiv10000, 2);
-                                                swap_endian((unsigned char*) &numberOfItems, 2);
-
-                                                if (processData)
-                                                {
-                                                    unsigned short* data = (unsigned short*)(receiveBuffer + parseOff + 21);
-
-                                                    unsigned char* swapPtr = (unsigned char*) data;
-                                                    // copy RSSI-Values +2 for 16-bit values +1 for 8-bit value
-                                                    for (int i = 0;
-                                                         i < numberOfItems * processDataLenValuesInBytes; i += processDataLenValuesInBytes)
-                                                    {
-                                                        if (processDataLenValuesInBytes == 1)
-                                                        {
-                                                        }
-                                                        else
-                                                        {
-                                                            unsigned char tmp;
-                                                            tmp = swapPtr[i + 1];
-                                                            swapPtr[i + 1] = swapPtr[i];
-                                                            swapPtr[i] = tmp;
-                                                        }
-                                                    }
-                                                    int idx = 0;
-
-                                                    switch (task)
-                                                    {
-
-                                                        case process_dist:
-                                                        {
-                                                            startAngle = startAngleDiv10000 / 10000.00;
-                                                            sizeOfSingleAngularStep = sizeOfSingleAngularStepDiv10000 / 10000.0;
-                                                            sizeOfSingleAngularStep *= (M_PI / 180.0);
-
-                                                            msg.angle_min = startAngle / 180.0 * M_PI - M_PI / 2;
-                                                            msg.angle_increment = sizeOfSingleAngularStep;
-                                                            msg.angle_max = msg.angle_min + (numberOfItems - 1) * msg.angle_increment;
-
-                                                            if (this->parser_->getCurrentParamPtr()->getScanMirroredAndShifted())
-                                                            {
-                                                                msg.angle_min -= M_PI / 2;
-                                                                msg.angle_max -= M_PI / 2;
-
-                                                                msg.angle_min *= -1.0;
-                                                                msg.angle_increment *= -1.0;
-                                                                msg.angle_max *= -1.0;
-
-                                                            }
-                                                            float* rangePtr = NULL;
-
-                                                            if (numberOfItems > 0)
-                                                            {
-                                                                rangePtr = &msg.ranges[0];
-                                                            }
-                                                            float scaleFactor_001 = 0.001F * scaleFactor;// to avoid repeated multiplication
-                                                            for (int i = 0; i < numberOfItems; i++)
-                                                            {
-                                                                idx = i + numberOfItems * (distChannelCnt - 1);
-                                                                rangePtr[idx] = (float) data[i] * scaleFactor_001 + scaleFactorOffset;
-#ifdef DEBUG_DUMP_ENABLED
-                                                                if (distChannelCnt == 1)
-                                                                {
-                                                                    if (i == floor(numberOfItems / 2))
-                                                                    {
-                                                                        double curTimeStamp = SystemCountScan + i * msg.time_increment * 1E6;
-                                                                        //DataDumper::instance().pushData(curTimeStamp, "DIST", rangePtr[idx]);
-                                                                    }
-                                                                }
-#endif
-                                                                //XXX
-                                                            }
-
-                                                        }
-                                                        break;
-                                                        case process_rssi:
-                                                        {
-                                                            // Das muss vom Protokoll abgeleitet werden. !!!
-
-                                                            float* intensityPtr = NULL;
-
-                                                            if (numberOfItems > 0)
-                                                            {
-                                                                intensityPtr = &msg.intensities[0];
-
-                                                            }
-                                                            for (int i = 0; i < numberOfItems; i++)
-                                                            {
-                                                                idx = i + numberOfItems * (rssiCnt - 1);
-                                                                // we must select between 16 bit and 8 bit values
-                                                                float rssiVal = 0.0;
-                                                                if (processDataLenValuesInBytes == 2)
-                                                                {
-                                                                    rssiVal = (float) data[i];
-                                                                }
-                                                                else
-                                                                {
-                                                                    unsigned char* data8Ptr = (unsigned char*) data;
-                                                                    rssiVal = (float) data8Ptr[i];
-                                                                }
-                                                                intensityPtr[idx] = rssiVal * scaleFactor + scaleFactorOffset;
-                                                            }
-                                                        }
-                                                        break;
-
-                                                        case process_vang:
-                                                            float* vangPtr = NULL;
-                                                            if (numberOfItems > 0)
-                                                            {
-                                                                vangPtr = &vang_vec[0]; // much faster, with vang_vec[i] each time the size will be checked
-                                                            }
-                                                            for (int i = 0; i < numberOfItems; i++)
-                                                            {
-                                                                vangPtr[i] = (float) data[i] * scaleFactor + scaleFactorOffset;
-                                                            }
-                                                            break;
-                                                    }
-                                                }
-                                                parseOff += 21 + processDataLenValuesInBytes * numberOfItems;
-
-
-                                            }
-                                            totalChannelCnt++;
-                                        }
-                                        while (bCont);
-                                    }
-#endif
+    count = 0;
+    cur_field = strtok(datagram, " ");
 
-                                    elevAngle = elevAngleX200 / 200.0;
-                                    scanFrequency = scanFrequencyX100 / 100.0;
-
-
-                                }
-                            }
-                        }
-
-
-                        parser_->checkScanTiming(msg.time_increment, msg.scan_time, msg.angle_increment, 0.00001f);
-
-                        success = sick_scan::ExitSuccess;
-                        // change Parsing Mode
-                        dataToProcess = false; // only one package allowed - no chaining
-                    }
-                    else // Parsing of Ascii-Encoding of datagram, xxx
-                    {
-                        dstart = strchr(buffer_pos, 0x02);
-                        if (dstart != NULL)
-                        {
-                            dend = strchr(dstart + 1, 0x03);
-                        }
-                        if ((dstart != NULL) && (dend != NULL))
-                        {
-                            dataToProcess = true; // continue parasing
-                            dlength = dend - dstart;
-                            *dend = '\0';
-                            dstart++;
-                        }
-                        else
-                        {
-                            dataToProcess = false;
-                            break; //
-                        }
-
-                        if (dumpDbg)
-                        {
-                            {
-                                static int cnt = 0;
-                                char szFileName[255];
+    while (cur_field != NULL)
+    {
+    fields.push_back(cur_field);
+    cur_field = strtok(NULL, " ");
+    }
+    count = fields.size();
 
-#ifdef _MSC_VER
-                                sprintf(szFileName, "c:\\temp\\dump%05d.txt", cnt);
-#else
-                                sprintf(szFileName, "/tmp/dump%05d.txt", cnt);
-#endif
-#if 0
-                                FILE* fout;
-                                fout = fopen(szFileName, "wb");
-                                fwrite(dstart, dlength, 1, fout);
-                                fclose(fout);
-#endif
-                                cnt++;
-                            }
-                        }
-
-                        // HEADER of data followed by DIST1 ... DIST2 ... DIST3 .... RSSI1 ... RSSI2.... RSSI3...
-
-                        // <frameid>_<sign>00500_DIST[1|2|3]
-                        numEchos = 1;
-                        // numEchos contains number of echos (1..5)
-                        // _msg holds ALL data of all echos
-                        success = parser_->parse_datagram(dstart, dlength, config_, msg, numEchos, echoMask);
-                        publishPointCloud = true; // for MRS1000
-
-                        numValidEchos = 0;
-                        for (int i = 0; i < maxAllowedEchos; i++)
-                        {
-                            aiValidEchoIdx[i] = 0;
-                        }
-                    }
-
-
-                    int numOfLayers = parser_->getCurrentParamPtr()->getNumberOfLayers();
-
-                    if (success == sick_scan::ExitSuccess)
-                    {
-                        bool elevationPreCalculated = false;
-                        double elevationAngleDegree = 0.0;
-
-
-                        std::vector<float> rangeTmp = msg.ranges;  // copy all range value
-                        std::vector<float> intensityTmp = msg.intensities; // copy all intensity value
-
-                        int intensityTmpNum = intensityTmp.size();
-                        float* intensityTmpPtr = NULL;
-                        if (intensityTmpNum > 0)
-                        {
-                            intensityTmpPtr = &intensityTmp[0];
-                        }
-
-                        // Helpful: https://answers.ros.org/question/191265/pointcloud2-access-data/
-                        // https://gist.github.com/yuma-m/b5dcce1b515335c93ce8
-                        // Copy to pointcloud
-                        int layer = 0;
-                        int baseLayer = 0;
-                        bool useGivenElevationAngle = false;
-                        switch (numOfLayers)
-                        {
-                            case 1: // TIM571 etc.
-                                baseLayer = 0;
-                                break;
-                            case 4:
-
-                                baseLayer = -1;
-                                if (msg.header.seq == 250)
-                                {
-                                    layer = -1;
-                                }
-                                else if (msg.header.seq == 0)
-                                {
-                                    layer = 0;
-                                }
-                                else if (msg.header.seq == -250)
-                                {
-                                    layer = 1;
-                                }
-                                else if (msg.header.seq == -500)
-                                {
-                                    layer = 2;
-                                }
-                                elevationAngleDegree = this->parser_->getCurrentParamPtr()->getElevationDegreeResolution();
-                                elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
-                                // 0.0436332 /*2.5 degrees*/;
-                                break;
-                            case 24: // Preparation for MRS6000
-                                baseLayer = -1;
-                                layer = (msg.header.seq - (-2638)) / 125;
-                                layer = (23 - layer) - 1;
-#if 0
-                                elevationAngleDegree = this->parser_->getCurrentParamPtr()->getElevationDegreeResolution();
-                                elevationAngleDegree = elevationAngleDegree / 180.0 * M_PI;
-#endif
+    if (verboseLevel > 0)
+    {
+    static int cnt = 0;
+    char szDumpFileName[511] = {0};
+    char szDir[255] = {0};
+
+    strcpy(szDir, "/tmp/");
+    sprintf(szDumpFileName, "%stmp%06d.txt", szDir, cnt);
+    ARMARX_WARNING("Verbose LEVEL activated. Only for DEBUG.");
+    FILE* ftmp;
+    ftmp = fopen(szDumpFileName, "w");
+    if (ftmp != NULL)
+    {
+    for (uint i = 0; i < count; i++)
+    {
+    fprintf(ftmp, "%3d: %s\n", i, fields[i]);
+    }
+    fclose(ftmp);
+    }
+    cnt++;
+    }
 
-                                elevationPreCalculated = true;
-                                if (vang_vec.size() > 0)
-                                {
-                                    useGivenElevationAngle = true;
-                                }
-                                break;
-                            default:
-                                assert(0);
-                                break; // unsupported
-
-                        }
-
-
-
-
-
-                        // XXX  - HIER MEHRERE SCANS publish, falls Mehrzielszenario läuft
-                        if (numEchos > 5)
-                        {
-                            ROS_WARN("Too much echos");
-                        }
-                        else
-                        {
-
-                            size_t startOffset = 0;
-                            size_t endOffset = 0;
-                            int echoPartNum = msg.ranges.size() / numEchos;
-                            for (int i = 0; i < numEchos; i++)
-                            {
-
-                                bool sendMsg = false;
-                                if ((echoMask & (1 << i)) & outputChannelFlagId)
-                                {
-                                    aiValidEchoIdx[numValidEchos] = i; // save index
-                                    numValidEchos++;
-                                    sendMsg = true;
-                                }
-                                startOffset = i * echoPartNum;
-                                endOffset = (i + 1) * echoPartNum;
-
-                                msg.ranges.clear();
-                                msg.intensities.clear();
-                                msg.ranges = std::vector<float>(
-                                                 rangeTmp.begin() + startOffset,
-                                                 rangeTmp.begin() + endOffset);
-                                // check also for MRS1104
-                                if (endOffset <= intensityTmp.size() && (intensityTmp.size() > 0))
-                                {
-                                    msg.intensities = std::vector<float>(
-                                                          intensityTmp.begin() + startOffset,
-                                                          intensityTmp.begin() + endOffset);
-                                }
-                                else
-                                {
-                                    msg.intensities.resize(echoPartNum); // fill with zeros
-                                }
-                                {
-                                    // numEchos
-                                    char szTmp[255] = {0};
-                                    if (this->parser_->getCurrentParamPtr()->getNumberOfLayers() > 1)
-                                    {
-                                        const char* cpFrameId = config_.frame_id.c_str();
-#if 0
-                                        sprintf(szTmp, "%s_%+04d_DIST%d", cpFrameId, msg.header.seq, i + 1);
-#else // experimental
-                                        char szSignName[10] = {0};
-                                        if ((int) msg.header.seq < 0)
-                                        {
-                                            strcpy(szSignName, "NEG");
-                                        }
-                                        else
-                                        {
-                                            strcpy(szSignName, "POS");
-
-                                        }
-
-                                        sprintf(szTmp, "%s_%s_%03d_DIST%d", cpFrameId, szSignName, abs((int) msg.header.seq), i + 1);
-#endif
-                                    }
-                                    else
-                                    {
-                                        strcpy(szTmp, config_.frame_id.c_str());
-                                    }
-
-                                    msg.header.frame_id = std::string(szTmp);
-                                    // Hector slam can only process ONE valid frame id.
-                                    if (echoForSlam.length() > 0)
-                                    {
-                                        if (slamBundle)
-                                        {
-                                            // try to map first echos to horizontal layers.
-                                            if (i == 0)
-                                            {
-                                                // first echo
-                                                msg.header.frame_id = echoForSlam;
-                                                strcpy(szTmp, echoForSlam.c_str());  //
-                                                if (elevationAngleInRad != 0.0)
-                                                {
-                                                    float cosVal = cos(elevationAngleInRad);
-                                                    int rangeNum = msg.ranges.size();
-                                                    for (int j = 0; j < rangeNum; j++)
-                                                    {
-                                                        msg.ranges[j] *= cosVal;
-                                                    }
-                                                }
-                                            }
-                                        }
-
-                                        if (echoForSlam.compare(szTmp) == 0)
-                                        {
-                                            sendMsg = true;
-                                        }
-                                        else
-                                        {
-                                            sendMsg = false;
-                                        }
-                                    }
-
-                                }
-#ifndef _MSC_VER
-                                if (parser_->getCurrentParamPtr()->getEncoderMode() >= 0 && FireEncoder == true)//
-                                {
-                                    Encoder_pub.publish(EncoderMsg);
-                                }
-                                if (numOfLayers > 4)
-                                {
-                                    sendMsg = false; // too many layers for publish as scan message. Only pointcloud messages will be pub.
-                                }
-                                if (sendMsg&
-                                    outputChannelFlagId)  // publish only configured channels - workaround for cfg-bug MRS1104
-                                {
-
-                                    pub_.publish(msg);
-                                }
-#else
-                                printf("MSG received...");
-#endif
-                            }
-                        }
-
-
-                        if (publishPointCloud == true)
-                        {
-
-
-                            const int numChannels = 4; // x y z i (for intensity)
-
-                            int numTmpLayer = numOfLayers;
-
-
-                            cloud_.header.stamp = recvTimeStamp + ros::Duration(config_.time_offset);
-
-
-                            cloud_.header.frame_id = config_.frame_id;
-                            cloud_.header.seq = 0;
-                            cloud_.height = numTmpLayer * numValidEchos; // due to multi echo multiplied by num. of layers
-                            cloud_.width = msg.ranges.size();
-                            cloud_.is_bigendian = false;
-                            cloud_.is_dense = true;
-                            cloud_.point_step = numChannels * sizeof(float);
-                            cloud_.row_step = cloud_.point_step * cloud_.width;
-                            cloud_.fields.resize(numChannels);
-                            for (int i = 0; i < numChannels; i++)
-                            {
-                                std::string channelId[] = {"x", "y", "z", "intensity"};
-                                cloud_.fields[i].name = channelId[i];
-                                cloud_.fields[i].offset = i * sizeof(float);
-                                cloud_.fields[i].count = 1;
-                                cloud_.fields[i].datatype = sensor_msgs::PointField::FLOAT32;
-                            }
-
-                            cloud_.data.resize(cloud_.row_step * cloud_.height);
-
-                            unsigned char* cloudDataPtr = &(cloud_.data[0]);
-
-
-                            // prepare lookup for elevation angle table
-
-                            std::vector<float> cosAlphaTable; // Lookup table for cos
-                            std::vector<float> sinAlphaTable; // Lookup table for sin
-                            size_t rangeNum = rangeTmp.size() / numValidEchos;
-                            cosAlphaTable.resize(rangeNum);
-                            sinAlphaTable.resize(rangeNum);
-                            float mirror_factor = 1.0;
-                            float angleShift = 0;
-                            if (this->parser_->getCurrentParamPtr()->getScanMirroredAndShifted())
-                            {
-                                //                mirror_factor = -1.0;
-                                //                angleShift = +M_PI/2.0; // add 90 deg for NAV3xx-series
-                            }
-
-                            for (size_t iEcho = 0; iEcho < numValidEchos; iEcho++)
-                            {
-
-                                float angle = config_.min_ang;
-
-
-                                float* cosAlphaTablePtr = &cosAlphaTable[0];
-                                float* sinAlphaTablePtr = &sinAlphaTable[0];
-
-                                float* vangPtr = NULL;
-                                float* rangeTmpPtr = &rangeTmp[0];
-                                if (vang_vec.size() > 0)
-                                {
-                                    vangPtr = &vang_vec[0];
-                                }
-                                for (size_t i = 0; i < rangeNum; i++)
-                                {
-                                    enum enum_index_descr
-                                    {
-                                        idx_x,
-                                        idx_y,
-                                        idx_z,
-                                        idx_intensity,
-                                        idx_num
-                                    };
-                                    long adroff = i * (numChannels * (int) sizeof(float));
-
-                                    adroff += (layer - baseLayer) * cloud_.row_step;
-
-                                    adroff += iEcho * cloud_.row_step * numTmpLayer;
-
-                                    unsigned char* ptr = cloudDataPtr + adroff;
-                                    float* fptr = (float*)(cloudDataPtr + adroff);
-
-                                    geometry_msgs::Point32 point;
-                                    float range_meter = rangeTmpPtr[iEcho * rangeNum + i];
-                                    float phi = angle; // azimuth angle
-                                    float alpha = 0.0;  // elevation angle
-
-                                    if (useGivenElevationAngle) // FOR MRS6124
-                                    {
-                                        alpha = -vangPtr[i] * deg2rad_const;
-                                    }
-                                    else
-                                    {
-                                        if (elevationPreCalculated) // FOR MRS6124 without VANGL
-                                        {
-                                            alpha = elevationAngleInRad;
-                                        }
-                                        else
-                                        {
-                                            alpha = layer * elevationAngleDegree; // for MRS1104
-                                        }
-                                    }
-
-                                    if (iEcho == 0)
-                                    {
-                                        cosAlphaTablePtr[i] = cos(alpha); // for z-value (elevation)
-                                        sinAlphaTablePtr[i] = sin(alpha);
-                                    }
-                                    else
-                                    {
-                                        // Just for Debugging: printf("%3d %8.3lf %8.3lf\n", (int)i, cosAlphaTablePtr[i], sinAlphaTablePtr[i]);
-                                    }
-                                    // Thanks to Sebastian Pütz <spuetz@uos.de> for his hint
-                                    float rangeCos = range_meter * cosAlphaTablePtr[i];
-
-                                    double phi_used = phi  + angleShift;
-                                    if (this->angleCompensator != NULL)
-                                    {
-                                        phi_used = angleCompensator->compensateAngleInRadFromRos(phi_used);
-                                    }
-                                    fptr[idx_x] = rangeCos * cos(phi_used);  // copy x value in pointcloud
-                                    fptr[idx_y] = rangeCos * sin(phi_used);  // copy y value in pointcloud
-                                    fptr[idx_z] = range_meter * sinAlphaTablePtr[i] * mirror_factor;// copy z value in pointcloud
-
-                                    fptr[idx_intensity] = 0.0;
-                                    if (config_.intensity)
-                                    {
-                                        int intensityIndex = aiValidEchoIdx[iEcho] * rangeNum + i;
-                                        // intensity values available??
-                                        if (intensityIndex < intensityTmpNum)
-                                        {
-                                            fptr[idx_intensity] = intensityTmpPtr[intensityIndex]; // copy intensity value in pointcloud
-                                        }
-                                    }
-                                    angle += msg.angle_increment;
-                                }
-                                // Publish
-                                static int cnt = 0;
-                                int layerOff = (layer - baseLayer);
-
-                            }
-                            // if ( (msg.header.seq == 0) || (layerOff == 0)) // FIXEN!!!!
-                            bool shallIFire = false;
-                            if ((msg.header.seq == 0) || (msg.header.seq == 237))
-                            {
-                                shallIFire = true;
-                            }
-
-
-                            static int layerCnt = 0;
-                            static int layerSeq[4];
-
-                            if (config_.cloud_output_mode > 0)
-                            {
-
-                                layerSeq[layerCnt % 4] = layer;
-                                if (layerCnt >= 4)  // mind. erst einmal vier Layer zusammensuchen
-                                {
-                                    shallIFire = true; // here are at least 4 layers available
-                                }
-                                else
-                                {
-                                    shallIFire = false;
-                                }
-
-                                layerCnt++;
-                            }
-
-                            if (shallIFire) // shall i fire the signal???
-                            {
-#ifdef ROSSIMU
-                                static int cnt = 0;
-                                cnt++;
 
-                                printf("PUBLISH_DATA:\n");
+    ARMARX_INFO("parse_datagram(): Validate header");
+    // Validate header. Total number of tokens is highly unreliable as this may
+    // change when you change the scanning range or the device name using SOPAS ET
+    // tool. The header remains stable, however.
+    if (count < HEADER_FIELDS)
+    {
+    ARMARX_WARNING(
+    "received less fields than minimum fields (actual: %d, minimum: %d), ignoring scan", (int) count,
+    HEADER_FIELDS);
+    ARMARX_WARNING(
+    "are you using the correct node? (124 --> sick_tim310_1130000m01, > 33 --> sick_tim551_2050001, 580 --> sick_tim310s01, 592 --> sick_tim310)");
+    // ROS_DEBUG("received message was: %s", datagram_copy);
+    return sick_scan::ExitError;
+    }
 
-                                unsigned char* cloudDataPtr = &(cloud_.data[0]);
-                                int w = cloud_.width;
-                                int h = cloud_.height;
+    if (strcmp(fields[15], "0"))
+    {
+    ARMARX_WARNING("Field 15 of received data is not equal to 0 (%s). Unexpected data, ignoring scan", fields[15]);
+    return sick_scan::ExitError;
+    }
+    if (strcmp(fields[20], "DIST1"))
+    {
+    ARMARX_WARNING("Field 20 of received data is not equal to DIST1i (%s). Unexpected data, ignoring scan", fields[20]);
+    return sick_scan::ExitError;
+    }
 
-                                int numShots = w * h;
+    // More in depth checks: check data length and RSSI availability
+    // 25: Number of data (<= 10F)
+    unsigned short int number_of_data = 0;
+    sscanf(fields[25], "%hx", &number_of_data);
 
-                                float* ptr = (float*) cloudDataPtr;
+    int numOfExpectedShots = parser_ptr->basicParams[scannerIdx].getNumberOfShots();
+    if (number_of_data < 1 || number_of_data > numOfExpectedShots)
+    {
+    ARMARX_WARNING("Data length is outside acceptable range 1-%d (%d). Ignoring scan", numOfExpectedShots, number_of_data);
+    return sick_scan::ExitError;
+    }
+    if (count < HEADER_FIELDS + number_of_data)
+    {
+    ARMARX_WARNING("Less fields than expected for %d data points (%zu). Ignoring scan", number_of_data, count);
+    return sick_scan::ExitError;
+    }
+    ROS_DEBUG("Number of data: %d", number_of_data);
 
-                                if (cnt == 25)
-                                {
-                                    char jpgFileName_tmp[255] = { 0 };
-#if linux
-                                    strcpy(jpgFileName_tmp, "./demo/scan.jpg_tmp");
-#else
-                                    strcpy(jpgFileName_tmp, "..\\demo\\scan.jpg_tmp");
-#endif
-                                    int xic = 400;
-                                    int yic = 400;
-                                    int w2i = 400;
-                                    int h2i = 400;
-                                    int hi = h2i * 2 + 1;
-                                    int wi = w2i * 2 + 1;
-                                    int pixNum = hi * wi;
-                                    int numColorChannel = 3;
-                                    unsigned char* pixel = (unsigned char*) malloc(numColorChannel * hi * wi);
-                                    memset(pixel, 0, numColorChannel * pixNum);
-                                    double scaleFac = 50.0;
-
-                                    for (int i = 0; i < hi; i++)
-                                    {
-                                        int pixAdr = numColorChannel * (i * wi + xic);
-                                        pixel[pixAdr] = 0x40;
-                                        pixel[pixAdr + 1] = 0x40;
-                                        pixel[pixAdr + 2] = 0x40;
-                                    }
-                                    for (int i = 0; i < wi; i++)
-                                    {
-                                        int pixAdr = numColorChannel * (yic * wi + i);
-                                        pixel[pixAdr] = 0x40;
-                                        pixel[pixAdr + 1] = 0x40;
-                                        pixel[pixAdr + 2] = 0x40;
-                                    }
-
-                                    scaleFac *= -1.0;
-                                    for (int i = 0; i < numShots; i++)
-                                    {
-                                        double x, y, z, intensity;
-                                        x = ptr[0];
-                                        y = ptr[1];
-                                        z = ptr[2];
-                                        intensity = ptr[3];
-                                        ptr += 4;
-                                        int xi = (x * scaleFac) + xic;
-                                        int yi = (y * scaleFac) + yic;
-                                        if ((xi >= 0) && (xi < wi))
-                                        {
-                                            if ((yi >= 0) && (xi < hi))
-                                            {
-                                                // yi shows left (due to neg. scaleFac)
-                                                // xi shows up (due to neg. scaleFac)
-                                                int pixAdr = numColorChannel * (xi * wi + yi);
-                                                int layer = i / w;
-                                                unsigned char color[3] = {0x00};
-                                                switch (layer)
-                                                {
-                                                    case 0:
-                                                        color[0] = 0xFF;
-                                                        break;
-                                                    case 1:
-                                                        color[1] = 0xFF;
-                                                        break;
-                                                    case 2:
-                                                        color[2] = 0xFF;
-                                                        break;
-                                                    case 3:
-                                                        color[0] = 0xFF;
-                                                        color[1] = 0xFF;
-                                                        break;
-                                                }
-
-                                                for (int kk = 0; kk < 3; kk++)
-                                                {
-                                                    pixel[pixAdr + kk] = color[kk];
-
-                                                }
-                                            }
-                                        }
-
-                                    }
-
-
-
-                                    // Write JPEG Scan Top View
-                                    foutJpg = fopen(jpgFileName_tmp, "wb");
-                                    if (foutJpg == NULL)
-                                    {
-                                        ROS_INFO("PANIC: Can not open %s for writing. Check existience of demo dir. or patch  code.\n", jpgFileName_tmp);
-                                    }
-                                    else
-                                    {
-                                        TooJpeg::writeJpeg(jpegOutputCallback, pixel, wi, hi, true, 99);
-                                        fclose(foutJpg);
-
-                                        free(pixel);
+    // Calculate offset of field that contains indicator of whether or not RSSI data is included
+    size_t rssi_idx = 26 + number_of_data;
+    bool rssi = false;
+    if (strcmp(fields[rssi_idx], "RSSI1") == 0)
+    {
+    rssi = true;
+    }
+    unsigned short int number_of_rssi_data = 0;
+    if (rssi)
+    {
+    sscanf(fields[rssi_idx + 5], "%hx", &number_of_rssi_data);
 
-#if linux
-                                        rename(jpgFileName_tmp, "./demo/scan.jpg");
-#else
-                                        _unlink("..\\demo\\scan.jpg");
-                                        rename(jpgFileName_tmp, "..\\demo\\scan.jpg");
-#endif
+    // Number of RSSI data should be equal to number of data
+    if (number_of_rssi_data != number_of_data)
+    {
+    ARMARX_WARNING("Number of RSSI data is lower than number of range data (%d vs %d", number_of_data,
+       number_of_rssi_data);
+    return sick_scan::ExitError;
+    }
 
-                                    }
-                                    // Write CSV-File
-                                    char csvFileNameTmp[255];
-#if linux
-                                    strcpy(csvFileNameTmp, "./demo/scan.csv_tmp");
-#else
-                                    strcpy(csvFileNameTmp, "..\\demo\\scan.csv_tmp");
-#endif
-                                    FILE* foutCsv = fopen(csvFileNameTmp, "w");
-                                    if (foutCsv)
-                                    {
-                                        // ZIEL: fprintf(foutCsv,"timestamp;range;elevation;azimuth;x;y;z;intensity\n");
-                                        fprintf(foutCsv, "timestamp_sec;timestamp_nanosec;range;azimuth_deg;elevation_deg;x;y;z;intensity\n");
-                                        unsigned char* cloudDataPtr = &(cloud_.data[0]);
-
-                                        int numShots = w * h;
-
-                                        float* ptr = (float*) cloudDataPtr;
-
-
-                                        long timestamp_sec = cloud_.header.stamp.sec;
-                                        long timestamp_nanosec = cloud_.header.stamp.nsec;
-                                        for (int i = 0; i < numShots; i++)
-                                        {
-                                            double x, y, z, intensity;
-                                            x = ptr[0];
-                                            y = ptr[1];
-                                            z = ptr[2];
-                                            float range_xy = sqrt(x * x + y * y);
-                                            float range_xyz = sqrt(x * x + y * y + z * z);
-                                            float elevation = atan2(z, range_xy);
-                                            float azimuth = atan2(y, x);
-                                            float elevationDeg = elevation * 180.0 / M_PI;
-                                            float azimuthDeg = azimuth * 180.0 / M_PI;
-
-                                            intensity = ptr[3];
-                                            ptr += 4;
-                                            fprintf(foutCsv, "%12ld;%12ld;%8.3lf;%8.3lf;%8.3lf;%8.3f;%8.3f;%8.3f;%8.0f\n", timestamp_sec, timestamp_nanosec, range_xyz, azimuthDeg, elevationDeg, x, y, z, intensity);
-                                        }
-                                        fclose(foutCsv);
-#ifdef linux
-                                        rename(csvFileNameTmp, "./demo/scan.csv");
-#else
-                                        _unlink("..\\demo\\scan.csv");
-                                        rename(csvFileNameTmp, "..\\demo\\scan.csv");
-#endif
-                                    }
-                                    else
-                                    {
-                                        ROS_INFO("PANIC: Can not open %s for writing. Check existience of demo dir. or patch  code.\n", csvFileNameTmp);
-                                    }
-                                    cnt = 0;
-                                }
+    // Check if the total length is still appropriate.
+    // RSSI data size = number of RSSI readings + 6 fields describing the data
+    if (count < HEADER_FIELDS + number_of_data + number_of_rssi_data + 6)
+    {
+    ARMARX_WARNING("Less fields than expected for %d data points (%zu). Ignoring scan", number_of_data, count);
+    return sick_scan::ExitError;
+    }
 
-#else
-                                if (config_.cloud_output_mode == 0)
-                                {
-                                    // standard handling of scans
-                                    cloud_pub_.publish(cloud_);
+    if (strcmp(fields[rssi_idx], "RSSI1"))
+    {
+    ARMARX_WARNING("Field %zu of received data is not equal to RSSI1 (%s). Unexpected data, ignoring scan", rssi_idx + 1,
+       fields[rssi_idx + 1]);
+    }
+    }
 
-                                }
+    ARMARX_INFO("parse_datagram(): Checks complete");
+
+    // ----- read fields into msg
+    msg.header.frame_id = config.frame_id;
+    // evtl. debug stream benutzen
+    // ROS_DEBUG("publishing with frame_id %s", config.frame_id.c_str());
+
+    ros::Time start_time = ros::Time::now(); // will be adjusted in the end
+
+    // <STX> (\x02)
+    // 0: Type of command (SN)
+    // 1: Command (LMDscandata)
+    // 2: Firmware version number (1)
+    // 3: Device number (1)
+    // 4: Serial number (eg. B96518)
+    // 5 + 6: Device Status (0 0 = ok, 0 1 = error)
+    // 7: Telegram counter (eg. 99)
+    // 8: Scan counter (eg. 9A)
+    // 9: Time since startup (eg. 13C8E59)
+    // 10: Time of transmission (eg. 13C9CBE)
+    // 11 + 12: Input status (0 0)
+    // 13 + 14: Output status (8 0)
+    // 15: Reserved Byte A (0)
+    // 16: Scanning Frequency (5DC)
+    unsigned short scanning_freq = -1;
+    sscanf(fields[16], "%hx", &scanning_freq);
+    msg.scan_time = 1.0 / (scanning_freq / 100.0);
+    // ROS_DEBUG("hex: %s, scanning_freq: %d, scan_time: %f", fields[16], scanning_freq, msg.scan_time);
+
+    // 17: Measurement Frequency (36)
+    unsigned short measurement_freq = -1;
+    sscanf(fields[17], "%hx", &measurement_freq);
+    msg.time_increment = 1.0 / (measurement_freq * 100.0);
+    // ROS_DEBUG("measurement_freq: %d, time_increment: %f", measurement_freq, msg.time_increment);
+
+    // 18: Number of encoders (0)
+    // 19: Number of 16 bit channels (1)
+    // 20: Measured data contents (DIST1)
+
+    // 21: Scaling factor (3F800000)
+    // ignored for now (is always 1.0):
+    //      unsigned int scaling_factor_int = -1;
+    //      sscanf(fields[21], "%x", &scaling_factor_int);
+    //
+    //      float scaling_factor = reinterpret_cast<float&>(scaling_factor_int);
+    //      // ROS_DEBUG("hex: %s, scaling_factor_int: %d, scaling_factor: %f", fields[21], scaling_factor_int, scaling_factor);
+
+    // 22: Scaling offset (00000000) -- always 0
+    // 23: Starting angle (FFF92230)
+    int starting_angle = -1;
+    sscanf(fields[23], "%x", &starting_angle);
+    msg.angle_min = (starting_angle / 10000.0) / 180.0 * M_PI - M_PI / 2;
+    // ROS_DEBUG("starting_angle: %d, angle_min: %f", starting_angle, msg.angle_min);
+
+    // 24: Angular step width (2710)
+    unsigned short angular_step_width = -1;
+    sscanf(fields[24], "%hx", &angular_step_width);
+    msg.angle_increment = (angular_step_width / 10000.0) / 180.0 * M_PI;
+    msg.angle_max = msg.angle_min + (number_of_data - 1) * msg.angle_increment;
+
+    // 25: Number of data (<= 10F)
+    // This is already determined above in number_of_data
+    int index_min = 0;
+
+    ARMARX_INFO("parse_datagram(): Parsing");
+    #if 1  // neuer Ansatz
+    int distNum = 0;
+    int rssiNum = 0;
+
+    param_ptr->checkForDistAndRSSI(fields, number_of_data, distNum, rssiNum, msg.ranges, msg.intensities, echoMask);
+    if (config.intensity)
+    {
+    if (rssiNum > 0)
+    {
 
-                                //                cloud_pub_.publish(cloud_);
-#endif
-                            }
-                        }
-                    }
-                    // Start Point
-                    if (dend != NULL)
-                    {
-                        buffer_pos = dend + 1;
-                    }
-                } // end of while loop
-            }
-
-            // shall we process more data? I.e. are there more packets to process in the input queue???
-
-        }
-        while ((packetsInLoop > 0) && (numPacketsProcessed < maxNumAllowedPacketsToProcess));
-        return sick_scan::ExitSuccess; // return success to continue looping
     }
+    else
+    {
+    ARMARX_WARNING("Intensity parameter is enabled, but the scanner is not configured to send RSSI values! "
+       "Please read the section 'Enabling intensity (RSSI) output' here: http://wiki.ros.org/sick_tim.");
+    }
+    }
+    numEchos = distNum;
+    #endif
+    // 26 + n: RSSI data included
+    // IF RSSI not included:
+    //   26 + n + 1 .. 26 + n + 3 = unknown (but seems to be [0, 1, B] always)
+    //   26 + n + 4 .. count - 4 = device label
+    //   count - 3 .. count - 1 = unknown (but seems to be 0 always)
+    //   <ETX> (\x03)
+
+    msg.range_min = override_range_min_;
+    msg.range_max = override_range_max_;
+
+    ARMARX_INFO("parse_datagram(): Time check");
+    float expected_time_increment =
+    fabs(param_ptr->getCurrentParamPtr()->getNumberOfLayers() * msg.scan_time * msg.angle_increment / (2.0 * M_PI));//If the direction of rotation is reversed, i.e. negative angle increment, a negative scan time results. This does not makes sense, therefore the absolute value is calculated.
+    if (fabs(expected_time_increment - msg.time_increment) > 0.00001)
+    {
+    ARMARX_WARNING("The time_increment, scan_time and angle_increment values reported by the scanner are inconsistent! "
+       "Expected time_increment: %.9f, reported time_increment: %.9f. "
+       "Perhaps you should set the parameter time_increment to the expected value. This message will print every 60 seconds.",
+       expected_time_increment, msg.time_increment);
+    }
+    return sick_scan::ExitSuccess;
+    }
+    */
 
     void SickScanAdapter::disconnectFunction()
     {
@@ -1532,41 +1288,27 @@ namespace armarx
 
     void SickScanAdapter::disconnectFunctionS(void* obj)
     {
-        if (obj != NULL)
-        {
-            ((SickScanAdapter*)(obj))->disconnectFunction();
-        }
+	if (obj != NULL)
+	{
+	    ((SickScanAdapter*)(obj))->disconnectFunction();
+	}
     }
 
     void SickScanAdapter::readCallbackFunctionS(void* obj, UINT8* buffer, UINT32& numOfBytes)
     {
-        ((SickScanAdapter*) obj)->readCallbackFunction(buffer, numOfBytes);
+	((SickScanAdapter*) obj)->readCallbackFunction(buffer, numOfBytes);
     }
 
 
     void SickScanAdapter::setReplyMode(int _mode)
     {
-        m_replyMode = _mode;
+	m_replyMode = _mode;
     }
 
     int SickScanAdapter::getReplyMode()
     {
-        return (m_replyMode);
-    }
-
-#if 0
-    void SickScanAdapter::setProtocolType(char cola_dialect_id)
-    {
-        if ((cola_dialect_id == 'a') || (cola_dialect_id == 'A'))
-        {
-            this->m_protocol = CoLa_A;
-        }
-        else
-        {
-            this->m_protocol = CoLa_B;
-        }
+	return (m_replyMode);
     }
-#endif
 
     /*!
     \brief Set emulation flag (using emulation instead of "real" scanner - currently implemented for radar
@@ -1575,7 +1317,7 @@ namespace armarx
     */
     void SickScanAdapter::setEmulSensor(bool _emulFlag)
     {
-        m_emulSensor = _emulFlag;
+	m_emulSensor = _emulFlag;
     }
 
     /*!
@@ -1585,7 +1327,7 @@ namespace armarx
     */
     bool SickScanAdapter::getEmulSensor()
     {
-        return (m_emulSensor);
+	return (m_emulSensor);
     }
 
     //
@@ -1597,173 +1339,173 @@ namespace armarx
     //
     SopasEventMessage SickScanAdapter::findFrameInReceiveBuffer()
     {
-        UINT32 frameLen = 0;
-        UINT32 i;
-
-        // Depends on protocol...
-        if (getProtocolType() == CoLa_A)
-        {
-            //
-            // COLA-A
-            //
-            // Must start with STX (0x02)
-            if (m_receiveBuffer[0] != 0x02)
-            {
-                // Look for starting STX (0x02)
-                for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
-                {
-                    if (m_receiveBuffer[i] == 0x02)
-                    {
-                        break;
-                    }
-                }
-
-                // Found beginning of frame?
-                if (i >= m_numberOfBytesInReceiveBuffer)
-                {
-                    // No start found, everything can be discarded
-                    m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
-                    return SopasEventMessage(); // No frame found
-                }
-
-                // Move frame start to index 0
-                UINT32 newLen = m_numberOfBytesInReceiveBuffer - i;
-                memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
-                m_numberOfBytesInReceiveBuffer = newLen;
-            }
-
-            // Look for ending ETX (0x03)
-            for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
-            {
-                if (m_receiveBuffer[i] == 0x03)
-                {
-                    break;
-                }
-            }
-
-            // Found end?
-            if (i >= m_numberOfBytesInReceiveBuffer)
-            {
-                // No end marker found, so it's not a complete frame (yet)
-                return SopasEventMessage(); // No frame found
-            }
-
-            // Calculate frame length in byte
-            frameLen = i + 1;
-
-            return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
-        }
-        else if (getProtocolType() == CoLa_B)
-        {
-            UINT32 magicWord;
-            UINT32 payloadlength;
-
-            if (m_numberOfBytesInReceiveBuffer < 4)
-            {
-                return SopasEventMessage();
-            }
-            UINT16 pos = 0;
-            magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
-            if (magicWord != 0x02020202)
-            {
-                // Look for starting STX (0x02020202)
-                for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
-                {
-                    pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
-                    magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
-                    if (magicWord == 0x02020202)
-                    {
-                        // found magic word
-                        break;
-                    }
-                }
-
-                // Found beginning of frame?
-                if (i > m_numberOfBytesInReceiveBuffer - 4)
-                {
-                    // No start found, everything can be discarded
-                    m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
-                    return SopasEventMessage(); // No frame found
-                }
-                else
-                {
-                    // Move frame start to index
-                    UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
-                    memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
-                    m_numberOfBytesInReceiveBuffer = bytesToMove;
-                }
-            }
-
-            // Pruefe Laenge des Pufferinhalts
-            if (m_numberOfBytesInReceiveBuffer < 9)
-            {
-                // Es sind nicht genug Daten fuer einen Frame
-                printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
-                                 ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
-                return SopasEventMessage();
-            }
-
-            // Read length of payload
-            pos = 4;
-            payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
-            printInfoMessage(
-                "SickScanCommonNw::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) +
-                " bytes.", m_beVerbose);
-
-            // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
-            if (payloadlength > (sizeof(m_receiveBuffer) - 9))
-            {
-                // magic word + length + checksum = 9
-                printWarning(
-                    "SickScanCommonNw::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
-                    + ::toString(payloadlength) + ".");
-                m_numberOfBytesInReceiveBuffer = 0;
-                return SopasEventMessage();
-            }
-            if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
-            {
-                // magic word + length + s + checksum = 10
-                printInfoMessage(
-                    "SickScanCommonNw::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
-                    ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
-                return SopasEventMessage(); // frame not complete
-            }
-
-            // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
-            frameLen = payloadlength + 9;
-
-            //
-            // test checksum of payload
-            //
-            UINT8 temp = 0;
-            UINT8 temp_xor = 0;
-            UINT8 checkSum;
-
-            // Read original checksum
-            pos = frameLen - 1;
-            checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
-
-            // Erzeuge die Pruefsumme zum Vergleich
-            for (UINT16 i = 8; i < (frameLen - 1); i++)
-            {
-                pos = i;
-                temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
-                temp_xor = temp_xor ^ temp;
-            }
-
-            // Vergleiche die Pruefsummen
-            if (temp_xor != checkSum)
-            {
-                printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
-                m_numberOfBytesInReceiveBuffer = 0;
-                return SopasEventMessage();
-            }
-
-            return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
-        }
-
-        // Return empty frame
-        return SopasEventMessage();
+	UINT32 frameLen = 0;
+	UINT32 i;
+
+	// Depends on protocol...
+	if (getProtocolType() == CoLa_A)
+	{
+	    //
+	    // COLA-A
+	    //
+	    // Must start with STX (0x02)
+	    if (m_receiveBuffer[0] != 0x02)
+	    {
+		// Look for starting STX (0x02)
+		for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
+		{
+		    if (m_receiveBuffer[i] == 0x02)
+		    {
+			break;
+		    }
+		}
+
+		// Found beginning of frame?
+		if (i >= m_numberOfBytesInReceiveBuffer)
+		{
+		    // No start found, everything can be discarded
+		    m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
+		    return SopasEventMessage(); // No frame found
+		}
+
+		// Move frame start to index 0
+		UINT32 newLen = m_numberOfBytesInReceiveBuffer - i;
+		memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), newLen);
+		m_numberOfBytesInReceiveBuffer = newLen;
+	    }
+
+	    // Look for ending ETX (0x03)
+	    for (i = 1; i < m_numberOfBytesInReceiveBuffer; i++)
+	    {
+		if (m_receiveBuffer[i] == 0x03)
+		{
+		    break;
+		}
+	    }
+
+	    // Found end?
+	    if (i >= m_numberOfBytesInReceiveBuffer)
+	    {
+		// No end marker found, so it's not a complete frame (yet)
+		return SopasEventMessage(); // No frame found
+	    }
+
+	    // Calculate frame length in byte
+	    frameLen = i + 1;
+
+	    return SopasEventMessage(m_receiveBuffer, CoLa_A, frameLen);
+	}
+	else if (getProtocolType() == CoLa_B)
+	{
+	    UINT32 magicWord;
+	    UINT32 payloadlength;
+
+	    if (m_numberOfBytesInReceiveBuffer < 4)
+	    {
+		return SopasEventMessage();
+	    }
+	    UINT16 pos = 0;
+	    magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
+	    if (magicWord != 0x02020202)
+	    {
+		// Look for starting STX (0x02020202)
+		for (i = 1; i <= m_numberOfBytesInReceiveBuffer - 4; i++)
+		{
+		    pos = i; // this is needed, as the position value is updated by getIntegerFromBuffer
+		    magicWord = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
+		    if (magicWord == 0x02020202)
+		    {
+			// found magic word
+			break;
+		    }
+		}
+
+		// Found beginning of frame?
+		if (i > m_numberOfBytesInReceiveBuffer - 4)
+		{
+		    // No start found, everything can be discarded
+		    m_numberOfBytesInReceiveBuffer = 0; // Invalidate buffer
+		    return SopasEventMessage(); // No frame found
+		}
+		else
+		{
+		    // Move frame start to index
+		    UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - i;
+		    memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[i]), bytesToMove); // payload+magic+length+s+checksum
+		    m_numberOfBytesInReceiveBuffer = bytesToMove;
+		}
+	    }
+
+	    // Pruefe Laenge des Pufferinhalts
+	    if (m_numberOfBytesInReceiveBuffer < 9)
+	    {
+		// Es sind nicht genug Daten fuer einen Frame
+		printInfoMessage("SickScanCommonNw::findFrameInReceiveBuffer: Frame cannot be decoded yet, only " +
+				 ::toString(m_numberOfBytesInReceiveBuffer) + " bytes in the buffer.", m_beVerbose);
+		return SopasEventMessage();
+	    }
+
+	    // Read length of payload
+	    pos = 4;
+	    payloadlength = colab::getIntegerFromBuffer<UINT32>(m_receiveBuffer, pos);
+	    printInfoMessage(
+		"SickScanCommonNw::findFrameInReceiveBuffer: Decoded payload length is " + ::toString(payloadlength) +
+		" bytes.", m_beVerbose);
+
+	    // Ist die Datenlaenge plausibel und wuede in den Puffer passen?
+	    if (payloadlength > (sizeof(m_receiveBuffer) - 9))
+	    {
+		// magic word + length + checksum = 9
+		printWarning(
+		    "SickScanCommonNw::findFrameInReceiveBuffer: Frame too big for receive buffer. Frame discarded with length:"
+		    + ::toString(payloadlength) + ".");
+		m_numberOfBytesInReceiveBuffer = 0;
+		return SopasEventMessage();
+	    }
+	    if ((payloadlength + 9) > m_numberOfBytesInReceiveBuffer)
+	    {
+		// magic word + length + s + checksum = 10
+		printInfoMessage(
+		    "SickScanCommonNw::findFrameInReceiveBuffer: Frame not complete yet. Waiting for the rest of it (" +
+		    ::toString(payloadlength + 9 - m_numberOfBytesInReceiveBuffer) + " bytes missing).", m_beVerbose);
+		return SopasEventMessage(); // frame not complete
+	    }
+
+	    // Calculate the total frame length in bytes: Len = Frame (9 bytes) + Payload
+	    frameLen = payloadlength + 9;
+
+	    //
+	    // test checksum of payload
+	    //
+	    UINT8 temp = 0;
+	    UINT8 temp_xor = 0;
+	    UINT8 checkSum;
+
+	    // Read original checksum
+	    pos = frameLen - 1;
+	    checkSum = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
+
+	    // Erzeuge die Pruefsumme zum Vergleich
+	    for (UINT16 i = 8; i < (frameLen - 1); i++)
+	    {
+		pos = i;
+		temp = colab::getIntegerFromBuffer<UINT8>(m_receiveBuffer, pos);
+		temp_xor = temp_xor ^ temp;
+	    }
+
+	    // Vergleiche die Pruefsummen
+	    if (temp_xor != checkSum)
+	    {
+		printWarning("SickScanCommonNw::findFrameInReceiveBuffer: Wrong checksum, Frame discarded.");
+		m_numberOfBytesInReceiveBuffer = 0;
+		return SopasEventMessage();
+	    }
+
+	    return SopasEventMessage(m_receiveBuffer, CoLa_B, frameLen);
+	}
+
+	// Return empty frame
+	return SopasEventMessage();
     }
 
 
@@ -1775,195 +1517,195 @@ namespace armarx
     void SickScanAdapter::processFrame(ros::Time timeStamp, SopasEventMessage& frame)
     {
 
-        if (getProtocolType() == CoLa_A)
-        {
-            printInfoMessage(
-                "SickScanCommonNw::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.",
-                m_beVerbose);
-            // processFrame_CoLa_A(frame);
-        }
-        else if (getProtocolType() == CoLa_B)
-        {
-            printInfoMessage(
-                "SickScanCommonNw::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.",
-                m_beVerbose);
-            // processFrame_CoLa_B(frame);
-        }
-
-        // Push frame to recvQueue
-
-        DatagramWithTimeStamp dataGramWidthTimeStamp(timeStamp, std::vector<unsigned char>(frame.getRawData(),
-                frame.getRawData() +
-                frame.size()));
-        // recvQueue.push(std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
-        recvQueue.push(dataGramWidthTimeStamp);
+	if (getProtocolType() == CoLa_A)
+	{
+	    printInfoMessage(
+		"SickScanCommonNw::processFrame: Calling processFrame_CoLa_A() with " + ::toString(frame.size()) + " bytes.",
+		m_beVerbose);
+	    // processFrame_CoLa_A(frame);
+	}
+	else if (getProtocolType() == CoLa_B)
+	{
+	    printInfoMessage(
+		"SickScanCommonNw::processFrame: Calling processFrame_CoLa_B() with " + ::toString(frame.size()) + " bytes.",
+		m_beVerbose);
+	    // processFrame_CoLa_B(frame);
+	}
+
+	// Push frame to recvQueue
+
+	DatagramWithTimeStamp dataGramWidthTimeStamp(timeStamp, std::vector<unsigned char>(frame.getRawData(),
+		frame.getRawData() +
+		frame.size()));
+	// recvQueue.push(std::vector<unsigned char>(frame.getRawData(), frame.getRawData() + frame.size()));
+	recvQueue.push(dataGramWidthTimeStamp);
     }
 
     void SickScanAdapter::readCallbackFunction(UINT8* buffer, UINT32& numOfBytes)
     {
-        ros::Time rcvTimeStamp = ros::Time::now(); // stamp received datagram
-        bool beVerboseHere = false;
-        printInfoMessage(
-            "SickScanCommonNw::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.",
-            beVerboseHere);
-
-        ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
-        UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
-        UINT32 bytesToBeTransferred = numOfBytes;
-        if (remainingSpace < numOfBytes)
-        {
-            bytesToBeTransferred = remainingSpace;
-            // printWarning("SickScanCommonNw::readCallbackFunction(): Input buffer space is to small, transferring only " +
-            //              ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
-        }
-        else
-        {
-            // printInfoMessage("SickScanCommonNw::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
-            //                   " bytes from TCP to input buffer.", beVerboseHere);
-        }
-
-        if (bytesToBeTransferred > 0)
-        {
-            // Data can be transferred into our input buffer
-            memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
-            m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
-
-            UINT32 size = 0;
-
-            while (1)
-            {
-                // Now work on the input buffer until all received datasets are processed
-                SopasEventMessage frame = findFrameInReceiveBuffer();
-
-                size = frame.size();
-                if (size == 0)
-                {
-                    // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
-                    // is incomplete, so leave the loop
-                    printInfoMessage("SickScanCommonNw::readCallbackFunction(): No complete frame in input buffer, we are done.",
-                                     beVerboseHere);
-
-                    // Leave the loop
-                    break;
-                }
-                else
-                {
-                    // A frame was found in the buffer, so process it now.
-                    printInfoMessage(
-                        "SickScanCommonNw::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) +
-                        " bytes.", beVerboseHere);
-                    processFrame(rcvTimeStamp, frame);
-                    UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - size;
-                    memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[size]), bytesToMove); // payload+magic+length+s+checksum
-                    m_numberOfBytesInReceiveBuffer = bytesToMove;
-
-                }
-            }
-        }
-        else
-        {
-            // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
-            // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
-            // we clear the input buffer here.
-            m_numberOfBytesInReceiveBuffer = 0;
-        }
+	ros::Time rcvTimeStamp = ros::Time::now(); // stamp received datagram
+	bool beVerboseHere = false;
+	printInfoMessage(
+	    "SickScanCommonNw::readCallbackFunction(): Called with " + toString(numOfBytes) + " available bytes.",
+	    beVerboseHere);
+
+	ScopedLock lock(&m_receiveDataMutex); // Mutex for access to the input buffer
+	UINT32 remainingSpace = sizeof(m_receiveBuffer) - m_numberOfBytesInReceiveBuffer;
+	UINT32 bytesToBeTransferred = numOfBytes;
+	if (remainingSpace < numOfBytes)
+	{
+	    bytesToBeTransferred = remainingSpace;
+	    // printWarning("SickScanCommonNw::readCallbackFunction(): Input buffer space is to small, transferring only " +
+	    //              ::toString(bytesToBeTransferred) + " of " + ::toString(numOfBytes) + " bytes.");
+	}
+	else
+	{
+	    // printInfoMessage("SickScanCommonNw::readCallbackFunction(): Transferring " + ::toString(bytesToBeTransferred) +
+	    //                   " bytes from TCP to input buffer.", beVerboseHere);
+	}
+
+	if (bytesToBeTransferred > 0)
+	{
+	    // Data can be transferred into our input buffer
+	    memcpy(&(m_receiveBuffer[m_numberOfBytesInReceiveBuffer]), buffer, bytesToBeTransferred);
+	    m_numberOfBytesInReceiveBuffer += bytesToBeTransferred;
+
+	    UINT32 size = 0;
+
+	    while (1)
+	    {
+		// Now work on the input buffer until all received datasets are processed
+		SopasEventMessage frame = findFrameInReceiveBuffer();
+
+		size = frame.size();
+		if (size == 0)
+		{
+		    // Framesize = 0: There is no valid frame in the buffer. The buffer is either empty or the frame
+		    // is incomplete, so leave the loop
+		    printInfoMessage("SickScanCommonNw::readCallbackFunction(): No complete frame in input buffer, we are done.",
+				     beVerboseHere);
+
+		    // Leave the loop
+		    break;
+		}
+		else
+		{
+		    // A frame was found in the buffer, so process it now.
+		    printInfoMessage(
+			"SickScanCommonNw::readCallbackFunction(): Processing a frame of length " + ::toString(frame.size()) +
+			" bytes.", beVerboseHere);
+		    processFrame(rcvTimeStamp, frame);
+		    UINT32 bytesToMove = m_numberOfBytesInReceiveBuffer - size;
+		    memmove(&(m_receiveBuffer[0]), &(m_receiveBuffer[size]), bytesToMove); // payload+magic+length+s+checksum
+		    m_numberOfBytesInReceiveBuffer = bytesToMove;
+
+		}
+	    }
+	}
+	else
+	{
+	    // There was input data from the TCP interface, but our input buffer was unable to hold a single byte.
+	    // Either we have not read data from our buffer for a long time, or something has gone wrong. To re-sync,
+	    // we clear the input buffer here.
+	    m_numberOfBytesInReceiveBuffer = 0;
+	}
     }
 
 
     int SickScanAdapter::init_device()
     {
-        int portInt;
-        sscanf(port_.c_str(), "%d", &portInt);
-        m_nw.init(hostname_, portInt, disconnectFunctionS, (void*) this);
-        m_nw.setReadCallbackFunction(readCallbackFunctionS, (void*) this);
-        if (this->getEmulSensor())
-        {
-            ROS_INFO("Sensor emulation is switched on - network traffic is switched off.");
-        }
-        else
-        {
-            m_nw.connect();
-        }
-        return sick_scan::ExitSuccess;
+	int portInt;
+	sscanf(port_.c_str(), "%d", &portInt);
+	m_nw.init(hostname_, portInt, disconnectFunctionS, (void*) this);
+	m_nw.setReadCallbackFunction(readCallbackFunctionS, (void*) this);
+	if (this->getEmulSensor())
+	{
+	    ARMARX_INFO_S << "Sensor emulation is switched on - network traffic is switched off.";
+	}
+	else
+	{
+	    m_nw.connect();
+	}
+	return sick_scan::ExitSuccess;
     }
 
     int SickScanAdapter::close_device()
     {
-        ROS_WARN("Disconnecting TCP-Connection.");
-        m_nw.disconnect();
-        return 0;
+	ARMARX_WARNING_S << "Disconnecting TCP-Connection.";
+	m_nw.disconnect();
+	return 0;
     }
 
 
     bool SickScanAdapter::stopScanData()
     {
-        stop_scanner();
-        return (true);
+	stop_scanner();
+	return (true);
     }
 
     void SickScanAdapter::handleRead(boost::system::error_code error, size_t bytes_transfered)
     {
-        ec_ = error;
-        bytes_transfered_ += bytes_transfered;
+	ec_ = error;
+	bytes_transfered_ += bytes_transfered;
     }
 
 
     void SickScanAdapter::checkDeadline()
     {
-        if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
-        {
-            // The reason the function is called is that the deadline expired. Close
-            // the socket to return all IO operations and reset the deadline
-            socket_.close();
-            deadline_.expires_at(boost::posix_time::pos_infin);
-        }
-
-        // Nothing bad happened, go back to sleep
-        deadline_.async_wait(boost::bind(&SickScanAdapter::checkDeadline, this));
+	if (deadline_.expires_at() <= boost::asio::deadline_timer::traits_type::now())
+	{
+	    // The reason the function is called is that the deadline expired. Close
+	    // the socket to return all IO operations and reset the deadline
+	    socket_.close();
+	    deadline_.expires_at(boost::posix_time::pos_infin);
+	}
+
+	// Nothing bad happened, go back to sleep
+	deadline_.async_wait(boost::bind(&SickScanAdapter::checkDeadline, this));
     }
 
 
     int SickScanAdapter::numberOfDatagramInInputFifo()
     {
-        int numVal = this->recvQueue.getNumberOfEntriesInQueue();
-        return (numVal);
+	int numVal = this->recvQueue.getNumberOfEntriesInQueue();
+	return (numVal);
     }
 
     int SickScanAdapter::readWithTimeout(size_t timeout_ms, char* buffer, int buffer_size, int* bytes_read,
-                                         bool* exception_occured, bool isBinary)
+					 bool* exception_occured, bool isBinary)
     {
-        // Set up the deadline to the proper timeout, error and delimiters
-        deadline_.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
-        const char end_delim = static_cast<char>(0x03);
-        int dataLen = 0;
-        ec_ = boost::asio::error::would_block;
-        bytes_transfered_ = 0;
-
-        size_t to_read;
-
-        int numBytes = 0;
-        // Polling - should be changed to condition variable in the future
-        int waitingTimeInMs = 1; // try to lookup for new incoming packages
-        size_t i;
-        for (i = 0; i < timeout_ms; i += waitingTimeInMs)
-        {
-            if (false == this->recvQueue.isQueueEmpty())
-            {
-                break;
-            }
-            boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
-        }
-        if (i >= timeout_ms)
-        {
-            ROS_ERROR("no answer received after %zu ms. Maybe sopas mode is wrong.\n", timeout_ms);
-            return (sick_scan::ExitError);
-        }
-        boost::condition_variable cond_;
-        DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
-
-        *bytes_read = datagramWithTimeStamp.datagram.size();
-        memcpy(buffer, &(datagramWithTimeStamp.datagram[0]), datagramWithTimeStamp.datagram.size());
-        return (sick_scan::ExitSuccess);
+	// Set up the deadline to the proper timeout, error and delimiters
+	deadline_.expires_from_now(boost::posix_time::milliseconds(timeout_ms));
+	const char end_delim = static_cast<char>(0x03);
+	int dataLen = 0;
+	ec_ = boost::asio::error::would_block;
+	bytes_transfered_ = 0;
+
+	size_t to_read;
+
+	int numBytes = 0;
+	// Polling - should be changed to condition variable in the future
+	int waitingTimeInMs = 1; // try to lookup for new incoming packages
+	size_t i;
+	for (i = 0; i < timeout_ms; i += waitingTimeInMs)
+	{
+	    if (false == this->recvQueue.isQueueEmpty())
+	    {
+		break;
+	    }
+	    boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
+	}
+	if (i >= timeout_ms)
+	{
+	    ROS_ERROR("no answer received after %zu ms. Maybe sopas mode is wrong.\n", timeout_ms);
+	    return (sick_scan::ExitError);
+	}
+	boost::condition_variable cond_;
+	DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
+
+	*bytes_read = datagramWithTimeStamp.datagram.size();
+	memcpy(buffer, &(datagramWithTimeStamp.datagram[0]), datagramWithTimeStamp.datagram.size());
+	return (sick_scan::ExitSuccess);
     }
 
     /**
@@ -1972,240 +1714,238 @@ namespace armarx
     int SickScanAdapter::sendSOPASCommand(const char* request, std::vector<unsigned char>* reply, int cmdLen)
     {
 #if 0
-        if (!socket_.is_open())
-        {
-            ROS_ERROR("sendSOPASCommand: socket not open");
-            diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: socket not open.");
-            return sick_scan::ExitError;
-        }
+	if (!socket_.is_open())
+	{
+	    ROS_ERROR("sendSOPASCommand: socket not open");
+	    diagnostics_.broadcast(getDiagnosticErrorCode(), "sendSOPASCommand: socket not open.");
+	    return sick_scan::ExitError;
+	}
 #endif
-        int sLen = 0;
-        int preambelCnt = 0;
-        bool cmdIsBinary = false;
-
-        if (request != NULL)
-        {
-            sLen = cmdLen;
-            preambelCnt = 0; // count 0x02 bytes to decide between ascii and binary command
-            if (sLen >= 4)
-            {
-                for (int i = 0; i < 4; i++)
-                {
-                    if (request[i] == 0x02)
-                    {
-                        preambelCnt++;
-                    }
-                }
-            }
-
-            if (preambelCnt < 4)
-            {
-                cmdIsBinary = false;
-            }
-            else
-            {
-                cmdIsBinary = true;
-            }
-            int msgLen = 0;
-            if (cmdIsBinary == false)
-            {
-                msgLen = strlen(request);
-            }
-            else
-            {
-                int dataLen = 0;
-                for (int i = 4; i < 8; i++)
-                {
-                    dataLen |= ((unsigned char) request[i] << (7 - i) * 8);
-                }
-                msgLen = 8 + dataLen + 1; // 8 Msg. Header + Packet +
-            }
+	int sLen = 0;
+	int preambelCnt = 0;
+	bool cmdIsBinary = false;
+
+	if (request != NULL)
+	{
+	    sLen = cmdLen;
+	    preambelCnt = 0; // count 0x02 bytes to decide between ascii and binary command
+	    if (sLen >= 4)
+	    {
+		for (int i = 0; i < 4; i++)
+		{
+		    if (request[i] == 0x02)
+		    {
+			preambelCnt++;
+		    }
+		}
+	    }
+
+	    if (preambelCnt < 4)
+	    {
+		cmdIsBinary = false;
+	    }
+	    else
+	    {
+		cmdIsBinary = true;
+	    }
+	    int msgLen = 0;
+	    if (cmdIsBinary == false)
+	    {
+		msgLen = strlen(request);
+	    }
+	    else
+	    {
+		int dataLen = 0;
+		for (int i = 4; i < 8; i++)
+		{
+		    dataLen |= ((unsigned char) request[i] << (7 - i) * 8);
+		}
+		msgLen = 8 + dataLen + 1; // 8 Msg. Header + Packet +
+	    }
 #if 1
-            if (getEmulSensor())
-            {
-                emulateReply((UINT8*) request, msgLen, reply);
-            }
-            else
-            {
-                bool debugBinCmd = false;
-                if (debugBinCmd)
-                {
-                    printf("=== START HEX DUMP ===\n");
-                    for (int i = 0; i < msgLen; i++)
-                    {
-                        unsigned char* ptr = (UINT8*) request;
-                        printf("%02x ", ptr[i]);
-                    }
-                    printf("\n=== END HEX DUMP ===\n");
-                }
-                m_nw.sendCommandBuffer((UINT8*) request, msgLen);
-            }
+	    if (getEmulSensor())
+	    {
+		emulateReply((UINT8*) request, msgLen, reply);
+	    }
+	    else
+	    {
+		bool debugBinCmd = false;
+		if (debugBinCmd)
+		{
+		    printf("=== START HEX DUMP ===\n");
+		    for (int i = 0; i < msgLen; i++)
+		    {
+			unsigned char* ptr = (UINT8*) request;
+			printf("%02x ", ptr[i]);
+		    }
+		    printf("\n=== END HEX DUMP ===\n");
+		}
+		m_nw.sendCommandBuffer((UINT8*) request, msgLen);
+	    }
 #else
 
-            /*
-             * Write a SOPAS variable read request to the device.
-             */
-            try
-            {
-                boost::asio::write(socket_, boost::asio::buffer(request, msgLen));
-            }
-            catch (boost::system::system_error& e)
-            {
-                ROS_ERROR("write error for command: %s", request);
-                diagnostics_.broadcast(getDiagnosticErrorCode(), "Write error for sendSOPASCommand.");
-                return sick_scan::ExitError;
-            }
+	    /*
+	     * Write a SOPAS variable read request to the device.
+	     */
+	    try
+	    {
+		boost::asio::write(socket_, boost::asio::buffer(request, msgLen));
+	    }
+	    catch (boost::system::system_error& e)
+	    {
+		ROS_ERROR("write error for command: %s", request);
+		diagnostics_.broadcast(getDiagnosticErrorCode(), "Write error for sendSOPASCommand.");
+		return sick_scan::ExitError;
+	    }
 #endif
-        }
-
-        // Set timeout in 5 seconds
-        const int BUF_SIZE = 65536;
-        char buffer[BUF_SIZE];
-        int bytes_read;
-        // !!!
-        if (getEmulSensor())
-        {
-
-        }
-        else
-        {
-            if (readWithTimeout(getReadTimeOutInMs(), buffer, BUF_SIZE, &bytes_read, 0, cmdIsBinary) == sick_scan::ExitError)
-            {
-                ROS_INFO_THROTTLE(1.0, "sendSOPASCommand: no full reply available for read after %d ms", getReadTimeOutInMs());
-                diagnostics_.broadcast(getDiagnosticErrorCode(),
-                                       "sendSOPASCommand: no full reply available for read after timeout.");
-                return sick_scan::ExitError;
-            }
-
-
-            if (reply)
-            {
-                reply->resize(bytes_read);
-
-                std::copy(buffer, buffer + bytes_read, &(*reply)[0]);
-            }
-        }
-        return sick_scan::ExitSuccess;
+	}
+
+	// Set timeout in 5 seconds
+	const int BUF_SIZE = 65536;
+	char buffer[BUF_SIZE];
+	int bytes_read;
+	// !!!
+	if (getEmulSensor())
+	{
+
+	}
+	else
+	{
+	    if (readWithTimeout(getReadTimeOutInMs(), buffer, BUF_SIZE, &bytes_read, 0, cmdIsBinary) == sick_scan::ExitError)
+	    {
+		ARMARX_INFO_S << "sendSOPASCommand: no full reply available for read after (ms): " << getReadTimeOutInMs();
+		return sick_scan::ExitError;
+	    }
+
+
+	    if (reply)
+	    {
+		reply->resize(bytes_read);
+
+		std::copy(buffer, buffer + bytes_read, &(*reply)[0]);
+	    }
+	}
+	return sick_scan::ExitSuccess;
     }
 
 
     int SickScanAdapter::get_datagram(ros::Time& recvTimeStamp, unsigned char* receiveBuffer, int bufferSize,
-                                      int* actual_length,
-                                      bool isBinaryProtocol, int* numberOfRemainingFifoEntries)
+				      int* actual_length,
+				      bool isBinaryProtocol, int* numberOfRemainingFifoEntries)
     {
-        if (NULL != numberOfRemainingFifoEntries)
-        {
-            *numberOfRemainingFifoEntries = 0;
-        }
-        this->setReplyMode(1);
-
-        if (this->getEmulSensor())
-        {
+	if (NULL != numberOfRemainingFifoEntries)
+	{
+	    *numberOfRemainingFifoEntries = 0;
+	}
+	this->setReplyMode(1);
+
+	if (this->getEmulSensor())
+	{
 #ifndef ROSSIMU
-            // boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
-            ros::Time timeStamp = ros::Time::now();
-            uint32_t nanoSec = timeStamp.nsec;
-            double waitTime10Hz = 10.0 * (double) nanoSec / 1E9;  // 10th of sec. [0..10[
+	    // boost::this_thread::sleep(boost::posix_time::milliseconds(waitingTimeInMs));
+	    ros::Time timeStamp = ros::Time::now();
+	    uint32_t nanoSec = timeStamp.nsec;
+	    double waitTime10Hz = 10.0 * (double) nanoSec / 1E9;  // 10th of sec. [0..10[
 
-            uint32_t waitTime = (int) waitTime10Hz; // round down
+	    uint32_t waitTime = (int) waitTime10Hz; // round down
 
-            double waitTimeUntilNextTime10Hz = 1 / 10.0 * (1.0 - (waitTime10Hz - waitTime));
+	    double waitTimeUntilNextTime10Hz = 1 / 10.0 * (1.0 - (waitTime10Hz - waitTime));
 
-            ros::Duration(waitTimeUntilNextTime10Hz).sleep();
-            SickScanRadar radar(this);
-            radar.setEmulation(true);
-            radar.simulateAsciiDatagram(receiveBuffer, actual_length);
-            recvTimeStamp = ros::Time::now();
+	    ros::Duration(waitTimeUntilNextTime10Hz).sleep();
+	    SickScanRadar radar(this);
+	    radar.setEmulation(true);
+	    radar.simulateAsciiDatagram(receiveBuffer, actual_length);
+	    recvTimeStamp = ros::Time::now();
 #endif
-        }
-        else
-        {
-            const int maxWaitInMs = getReadTimeOutInMs();
-            std::vector<unsigned char> dataBuffer;
+	}
+	else
+	{
+	    const int maxWaitInMs = getReadTimeOutInMs();
+	    std::vector<unsigned char> dataBuffer;
 #if 1 // prepared for reconnect
-            bool retVal = this->recvQueue.waitForIncomingObject(maxWaitInMs);
-            if (retVal == false)
-            {
-                ROS_WARN("Timeout during waiting for new datagram");
-                return sick_scan::ExitError;
-            }
-            else
-            {
-                // Look into receiving queue for new Datagrams
-                //
-                //
-                DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
-                if (NULL != numberOfRemainingFifoEntries)
-                {
-                    *numberOfRemainingFifoEntries = this->recvQueue.getNumberOfEntriesInQueue();
-                }
-                recvTimeStamp = datagramWithTimeStamp.timeStamp;
-                dataBuffer = datagramWithTimeStamp.datagram;
-
-            }
+	    bool retVal = this->recvQueue.waitForIncomingObject(maxWaitInMs);
+	    if (retVal == false)
+	    {
+		ARMARX_WARNING_S << "Timeout during waiting for new datagram";
+		return sick_scan::ExitError;
+	    }
+	    else
+	    {
+		// Look into receiving queue for new Datagrams
+		//
+		//
+		DatagramWithTimeStamp datagramWithTimeStamp = this->recvQueue.pop();
+		if (NULL != numberOfRemainingFifoEntries)
+		{
+		    *numberOfRemainingFifoEntries = this->recvQueue.getNumberOfEntriesInQueue();
+		}
+		recvTimeStamp = datagramWithTimeStamp.timeStamp;
+		dataBuffer = datagramWithTimeStamp.datagram;
+
+	    }
 #endif
-            // dataBuffer = this->recvQueue.pop();
-            long size = dataBuffer.size();
-            memcpy(receiveBuffer, &(dataBuffer[0]), size);
-            *actual_length = size;
-        }
+	    // dataBuffer = this->recvQueue.pop();
+	    long size = dataBuffer.size();
+	    memcpy(receiveBuffer, &(dataBuffer[0]), size);
+	    *actual_length = size;
+	}
 
 #if 0
-        static int cnt = 0;
-        char szFileName[255];
-        sprintf(szFileName, "/tmp/dg%06d.bin", cnt++);
-
-        FILE* fout;
-
-        fout = fopen(szFileName, "wb");
-        if (fout != NULL)
-        {
-            fwrite(receiveBuffer, size, 1, fout);
-            fclose(fout);
-        }
+	static int cnt = 0;
+	char szFileName[255];
+	sprintf(szFileName, "/tmp/dg%06d.bin", cnt++);
+
+	FILE* fout;
+
+	fout = fopen(szFileName, "wb");
+	if (fout != NULL)
+	{
+	    fwrite(receiveBuffer, size, 1, fout);
+	    fclose(fout);
+	}
 #endif
-        return sick_scan::ExitSuccess;
-
-        if (!socket_.is_open())
-        {
-            ROS_ERROR("get_datagram: socket not open");
-            diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: socket not open.");
-            return sick_scan::ExitError;
-        }
-
-        /*
-         * Write a SOPAS variable read request to the device.
-         */
-        std::vector<unsigned char> reply;
-
-        // Wait at most 5000ms for a new scan
-        size_t timeout = 30000;
-        bool exception_occured = false;
-
-        char* buffer = reinterpret_cast<char*>(receiveBuffer);
-
-        if (readWithTimeout(timeout, buffer, bufferSize, actual_length, &exception_occured, isBinaryProtocol) !=
-            sick_scan::ExitSuccess)
-        {
-            ROS_ERROR_THROTTLE(1.0, "get_datagram: no data available for read after %zu ms", timeout);
-            diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: no data available for read after timeout.");
-
-            // Attempt to reconnect when the connection was terminated
-            if (!socket_.is_open())
-            {
+	return sick_scan::ExitSuccess;
+
+	if (!socket_.is_open())
+	{
+	    ROS_ERROR("get_datagram: socket not open");
+	    diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: socket not open.");
+	    return sick_scan::ExitError;
+	}
+
+	/*
+	 * Write a SOPAS variable read request to the device.
+	 */
+	std::vector<unsigned char> reply;
+
+	// Wait at most 5000ms for a new scan
+	size_t timeout = 30000;
+	bool exception_occured = false;
+
+	char* buffer = reinterpret_cast<char*>(receiveBuffer);
+
+	if (readWithTimeout(timeout, buffer, bufferSize, actual_length, &exception_occured, isBinaryProtocol) !=
+	    sick_scan::ExitSuccess)
+	{
+	    ROS_ERROR_THROTTLE(1.0, "get_datagram: no data available for read after %zu ms", timeout);
+	    diagnostics_.broadcast(getDiagnosticErrorCode(), "get_datagram: no data available for read after timeout.");
+
+	    // Attempt to reconnect when the connection was terminated
+	    if (!socket_.is_open())
+	    {
 #ifdef _MSC_VER
-                Sleep(1000);
+		Sleep(1000);
 #else
-                sleep(1);
+		sleep(1);
 #endif
-                ROS_INFO("Failure - attempting to reconnect");
-                return init();
-            }
+		ARMARX_INFO << "Failure - attempting to reconnect";
+		return init();
+	    }
 
-            return exception_occured ? sick_scan::ExitError : sick_scan::ExitSuccess;    // keep on trying
-        }
+	    return exception_occured ? sick_scan::ExitError : sick_scan::ExitSuccess;    // keep on trying
+	}
 
-        return sick_scan::ExitSuccess;
+	return sick_scan::ExitSuccess;
     }
 
 }
diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.h b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.h
index 08daf8276..d5ddd955e 100644
--- a/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.h
+++ b/source/RobotAPI/drivers/SickLaserUnit/SickScanAdapter.h
@@ -35,6 +35,8 @@
 #ifndef SICK_TIM3XX_COMMON_TCP_H
 #define SICK_TIM3XX_COMMON_TCP_H
 
+#include <ArmarXCore/core/Component.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -70,6 +72,9 @@ namespace armarx
     public:
         int loopOnce();
 
+        int parse_datagram(char* datagram, size_t datagram_length, sick_scan::SickScanConfig& config,
+                           sensor_msgs::LaserScan& msg, int& numEchos, int& echoMask);
+
         static void disconnectFunctionS(void* obj);
 
         SickScanAdapter(const std::string& hostname, const std::string& port, int& timelimit, sick_scan::SickGenericParser* parser,
@@ -161,6 +166,7 @@ namespace armarx
         boost::system::error_code ec_;
         size_t bytes_transfered_;
 
+        sick_scan::SickGenericParser* parser_ptr;
         std::string hostname_;
         std::string port_;
         int timelimit_;
-- 
GitLab