From ca18b0b91507c43b2f5892cf0fdead473e0c0468 Mon Sep 17 00:00:00 2001 From: Johann Mantel <j-mantel@gmx.net> Date: Fri, 25 Jun 2021 12:42:14 +0200 Subject: [PATCH] Add SickLaserScanDevice struct and methods to initialize and run the scanner --- .../drivers/SickLaserUnit/SickLaserUnit.cpp | 231 ++++++++++-------- .../drivers/SickLaserUnit/SickLaserUnit.h | 85 ++++--- 2 files changed, 180 insertions(+), 136 deletions(-) diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp index b99a4169a..184e7f23d 100644 --- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp +++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.cpp @@ -31,22 +31,93 @@ namespace armarx { - std::string protocolToString(SickLaserUnit::Protocol protocol) + std::string protocolToString(ScanProtocol protocol) { std::string protocolStr; - switch (protocol) { - case SickLaserUnit::Protocol::ASCII: + case ScanProtocol::ASCII: protocolStr = "ASCII"; break; - case SickLaserUnit::Protocol::Binary: + case ScanProtocol::Binary: protocolStr = "Binary"; break; } - return modeStr; + return protocolStr; + } + + + void SickLaserScanDevice::run() + { + while (!task->isStopped()) + { + switch (runState) + { + case RunState::scannerInit: + initScanner(); + break; + case RunState::scannerRun: + if (result == sick_scan::ExitSuccess) // OK -> loop again + { + result = scanner->loopOnce(); + } + else + { + runState = RunState::scannerFinalize; + } + break; + case RunState::scannerFinalize: + break; + default: + ARMARX_ERROR_S << "Invalid run state in task loop"; + break; + } + } } + void SickLaserScanDevice::initScanner() + { + this->isSensorInitialized = false; + ARMARX_INFO_S << "Start initialising scanner [Ip: " << this->ip + << "] [Port: " << this->port << "]"; + // attempt to connect/reconnect + delete this->scanner; // disconnect scanner + if (this->useTcp) + { + this->scanner = new sick_scan::SickScanCommonTcp(this->ip, this->port, this->timelimit, this->parser, this->colaDialectId); + } + 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; + + 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 + } + + } + else + { + this->runState = RunState::scannerInit; // If there was an error, try to restart scanner + } + } + + armarx::PropertyDefinitionsPtr SickLaserUnit::createPropertyDefinitions() { armarx::PropertyDefinitionsPtr def = @@ -67,8 +138,8 @@ namespace armarx 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(Protocol::ASCII), Protocol::ASCII) - .map(protocolToString(Protocol::Binary), Protocol::Binary); + .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"); @@ -92,65 +163,78 @@ namespace armarx ARMARX_INFO_S << "SickLaserUnit sagt Hallo Welt!"; + scanDevice.isSensorInitialized = false; if (properties.hostname != "") { - useTCP = true; + scanDevice.useTcp = true; + scanDevice.ip = properties.hostname; } - if (sNewIp != "") + if (properties.newIpAddress != "") { - changeIP = true; + scanDevice.changeIP = true; + scanDevice.newIpAddress = properties.newIpAddress; } + scanDevice.scannerType = properties.scannerType; //scanner Parameters - parser = new sick_scan::SickGenericParser(properties.scannerType); - parser->set_range_min(properties.rangeMin); - parser->set_range_max(properties.rangeMax); - parser->set_time_increment(properties.timeIncrement); - char colaDialectId = 'A'; // A or B (Ascii or Binary) + scanDevice.parser = new sick_scan::SickGenericParser(scanDevice.scannerType); + scanDevice.parser->set_range_min(properties.rangeMin); + scanDevice.parser->set_range_max(properties.rangeMax); + scanDevice.parser->set_time_increment(properties.timeIncrement); if (properties.emulSensor) { ARMARX_INFO_S << "Found paraemter emulSensor overwriting default settings. Emulation: True"; + scanDevice.emulSensor = true; } switch (properties.protocol) { - case Protocol::ASCII: - if (parser->getCurrentParamPtr()->getNumberOfLayers() > 4) + case ScanProtocol::ASCII: + if (scanDevice.parser->getCurrentParamPtr()->getNumberOfLayers() > 4) { - ARMARX_WARNING( - "This scanner type does not support ASCII communication.\n" - "Binary communication has been activated.\n" - "The parameter \"sopasProtocolType\" has been set to \"true\"."); - properties.sopasProtocolType = true; - properties.protocol = Protocol::Binary; + 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 Protocol::Binary: + 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."; - properties.protocol = Protocol::Binary; + scanDevice.protocol = ScanProtocol::Binary; } - if (properties.protocol == Protocol::ASCII) + if (scanDevice.protocol == ScanProtocol::ASCII) { - parser->getCurrentParamPtr()->setUseBinaryProtocol(false); - colaDialectId = 'A'; + scanDevice.parser->getCurrentParamPtr()->setUseBinaryProtocol(false); + scanDevice.colaDialectId = 'A'; } else { - parser->getCurrentParamPtr()->setUseBinaryProtocol(true); - colaDialectId = 'B'; + scanDevice.parser->getCurrentParamPtr()->setUseBinaryProtocol(true); + scanDevice.colaDialectId = 'B'; } - isSensorInitialized = false; } void SickLaserUnit::onConnectComponent() { - initScanner(); + //start the laser scanner + if (scanDevice.task) + { + scanDevice.task->stop(); + scanDevice.task = nullptr; + } + scanDevice.runState = RunState::scannerInit; + scanDevice.task = new RunningTask<SickLaserScanDevice>(&scanDevice, &SickLaserScanDevice::run, "SickLaserScanUpdate_" + scanDevice.ip); + scanDevice.task->start(); + // Do things after connecting to topics and components. /* (Requies the armarx::DebugObserverComponentPluginUser.) @@ -179,44 +263,21 @@ namespace armarx */ } - void SickLaserUnit::run() - { - while (!task->isStopped()) - { - switch (runState) - { - case RunState::scannerInit: - initScanner(); - break; - case RunState::scannerRun: - if (result == sick_scan::ExitSuccess) // OK -> loop again - { - result = scanner->loopOnce(); - } - else - { - runState = RunState::scannerFinalize; - } - break; - case RunState::scannerFinalize: - break; - default: - ARMARX_ERROR_S << "Invalid run state in mail loop"; - break; - } - } - } - void SickLaserUnit::onDisconnectComponent() { ARMARX_INFO_S << "Disconnecting LaserScanner."; - if (scanner != NULL) + if (scanDevice.task) + { + scanDevice.task->stop(); + scanDevice.task = nullptr; + } + if (scanDevice.scanner) { - delete scanner; + delete scanDevice.scanner; } - if (parser != NULL) + if (scanDevice.parser) { - delete parser; + delete scanDevice.parser; } } @@ -227,48 +288,6 @@ namespace armarx return "SickLaserUnit"; } - void SickLaserUnit::initScanner() - { - isSensorInitialized = false; - ARMARX_INFO("Start initialising scanner [Ip: %s] [Port: %s]", properties.hostname.c_str(), - properties.port.c_str()); - // attempt to connect/reconnect - delete scanner; // disconnect scanner - if (useTCP) - { - scanner = new sick_scan::SickScanCommonTcp(properties.hostname, properties.port, properties.timelimit, parser, - colaDialectId); - } - else - { - ARMARX_ERROR("TCP is not switched on. Probably hostname or port not set.\n"); - exit(); - } - - if (emulSensor) - { - scanner->setEmulSensor(true); - } - result = scanner->init(); - isSensorInitialized = true; - - if (result == sick_scan::ExitSuccess) // OK -> loop again - { - if (changeIP) - { - runState = RunState::scannerFinalize; - } - else - { - runState = RunState::scannerRun; // after initialising switch to run state - } - - } - else - { - runState = RunState::scannerInit; // If there was an error, try to restart scanner - } - } /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.) void SickLaserUnit::createRemoteGuiTab() { diff --git a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h index 81f8391e1..4c447b11e 100644 --- a/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h +++ b/source/RobotAPI/drivers/SickLaserUnit/SickLaserUnit.h @@ -25,7 +25,7 @@ // #include <mutex> #include <ArmarXCore/core/Component.h> - +#include <ArmarXCore/core/services/tasks/RunningTask.h> // #include // <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h> @@ -36,14 +36,62 @@ #include <vector> -#include 'include/sick_scan_base/include/sick_scan/sick_scan_common_tcp.h' +//#include "thirdparty/sick_scan_base/include/sick_scan/sick_scan_common.h" -#include 'include/sick_scan_base/include/sick_scan/sick_generic_parser.h' -#include 'include/sick_scan_base/include/sick_scan/sick_generic_laser.h' +#include <sick_scan/sick_scan_common_tcp.h> +#include <sick_scan/sick_scan_common.h> +#include <sick_scan/sick_generic_laser.h> namespace armarx { + enum class ScanProtocol + { + ASCII, + Binary + }; + + enum class RunState + { + scannerInit, + scannerRun, + scannerFinalize + }; + + struct SickLaserScanDevice + { + //scanner parameters + std::string scannerType; + int deviceNumber = 0; + double rangeMin; + double rangeMax; + double timeIncrement; + //communication parameters + std::string ip; + std::string newIpAddress = ""; + std::string port; + float angleOffset = 0.0f; + 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'; + //data and task pointers + std::vector<long> scanData; + RunState runState = RunState::scannerFinalize; + RunningTask<SickLaserScanDevice>::pointer_type task; + sick_scan::SickScanConfig cfg; + sick_scan::SickScanCommonTcp* scanner; + sick_scan::SickGenericParser* parser; + int result = sick_scan::ExitError; + bool isSensorInitialized = false; + + void initScanner(); + void run(); + }; /** * @defgroup Component-SickLaserUnit SickLaserUnit * @ingroup RobotAPI-Components @@ -63,17 +111,6 @@ namespace armarx public: /// @see armarx::ManagedIceObject::getDefaultName() std::string getDefaultName() const override; - enum class Protocol - { - ASCII, - Binary - }; - enum class RunState - { - scannerInit, - scannerRun, - scannerFinalize - }; protected: /// @see PropertyUser::createPropertyDefinitions() @@ -91,8 +128,6 @@ namespace armarx /// @see armarx::ManagedIceObject::onExitComponent() void onExitComponent() override; - void initScanner(); - /* (Requires armarx::LightweightRemoteGuiComponentPluginUser.) /// This function should be called once in onConnect() or when you /// need to re-create the Remote GUI tab. @@ -122,12 +157,12 @@ namespace armarx struct Properties { //communication parameters - std::string hostname = ""; + std::string hostname = "192.168.8.129"; std::string newIpAddress = ""; std::string port = "2112"; int timelimit = 5; bool subscribeDatagram = false; - Protocol protocol = Protocol::Binary; + ScanProtocol protocol = ScanProtocol::Binary; bool sopasProtocolType = false; //scanner parameters std::string scannerType; @@ -139,18 +174,8 @@ namespace armarx bool emulSensor = false; }; Properties properties; + SickLaserScanDevice scanDevice; - RunState runState; - - bool useTcp = false; - bool changeIP = false; - char colaDialectId = 'B'; - - int result = sick_scan::ExitError; - sick_scan::SickScanConfig cfg; - sick_scan::SickScanCommonTcp* scanner; - sick_scan::SickGenericParser* parser; - bool isSensorInitialized = false; /* Use a mutex if you access variables from different threads * (e.g. ice functions and RemoteGui_update()). std::mutex propertiesMutex; -- GitLab