From 3f64986f22bac046fa11ccab14c45404f9c1f9ad Mon Sep 17 00:00:00 2001
From: Fabian Paus <fabian.paus@kit.edu>
Date: Wed, 8 Mar 2017 14:56:53 +0100
Subject: [PATCH] Hokuyo: Added simple GUI plugin

---
 .../HokuyoLaserUnit/HokuyoLaserUnit.cpp       |   5 +
 .../drivers/HokuyoLaserUnit/HokuyoLaserUnit.h |   3 +-
 source/RobotAPI/gui-plugins/CMakeLists.txt    |   2 +
 .../LaserScannerPlugin/CMakeLists.txt         |  40 +++++
 .../LaserScannerPluginGuiPlugin.cpp           |  34 +++++
 .../LaserScannerPluginGuiPlugin.h             |  51 +++++++
 .../LaserScannerPluginWidget.ui               |  63 ++++++++
 .../LaserScannerPluginWidgetController.cpp    | 138 ++++++++++++++++++
 .../LaserScannerPluginWidgetController.h      | 131 +++++++++++++++++
 .../interface/units/LaserScannerUnit.ice      |   2 +
 10 files changed, 468 insertions(+), 1 deletion(-)
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/CMakeLists.txt
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.cpp
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.h
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidget.ui
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.cpp
 create mode 100644 source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.h

diff --git a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
index ac411a211..fc78cf268 100644
--- a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
+++ b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
@@ -134,6 +134,11 @@ armarx::PropertyDefinitionsPtr HokuyoLaserUnit::createPropertyDefinitions()
             getConfigIdentifier()));
 }
 
+std::string HokuyoLaserUnit::getReportTopicName(const Ice::Current& c) const
+{
+    return topicName;
+}
+
 void HokuyoLaserUnit::updateScanData()
 {
     LaserScan scan;
diff --git a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
index e8d018f39..2445d3a03 100644
--- a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
+++ b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
@@ -111,6 +111,8 @@ namespace armarx
          */
         virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions();
 
+        std::string getReportTopicName(const Ice::Current& c) const override;
+
     private:
         void updateScanData();
 
@@ -121,7 +123,6 @@ namespace armarx
         float angleOffset = 0.0f;
         std::vector<HokuyoLaserScanDevice> devices;
         PeriodicTask<HokuyoLaserUnit>::pointer_type task;
-
     };
 }
 
diff --git a/source/RobotAPI/gui-plugins/CMakeLists.txt b/source/RobotAPI/gui-plugins/CMakeLists.txt
index 8e1b05f0d..fc363790a 100644
--- a/source/RobotAPI/gui-plugins/CMakeLists.txt
+++ b/source/RobotAPI/gui-plugins/CMakeLists.txt
@@ -10,3 +10,5 @@ add_subdirectory(RobotViewerPlugin)
 
 add_subdirectory(DebugDrawerViewer)
 add_subdirectory(ViewSelection)
+
+add_subdirectory(LaserScannerPlugin)
\ No newline at end of file
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/CMakeLists.txt b/source/RobotAPI/gui-plugins/LaserScannerPlugin/CMakeLists.txt
new file mode 100644
index 000000000..1c1e4e282
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/CMakeLists.txt
@@ -0,0 +1,40 @@
+
+armarx_set_target("LaserScannerPluginGuiPlugin")
+
+find_package(Qt4 COMPONENTS QtCore QtGui QtDesigner)
+
+armarx_build_if(QT_FOUND "Qt not available")
+# ArmarXGui gets included through depends_on_armarx_package(ArmarXGui "OPTIONAL")
+# in the toplevel CMakeLists.txt
+armarx_build_if(ArmarXGui_FOUND "ArmarXGui not available")
+
+
+# all include_directories must be guarded by if(Xyz_FOUND)
+# for multiple libraries write: if(X_FOUND AND Y_FOUND)....
+if(QT_FOUND)
+    include(${QT_USE_FILE})
+endif()
+
+set(SOURCES
+./LaserScannerPluginGuiPlugin.cpp ./LaserScannerPluginWidgetController.cpp
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@GuiPlugin.cpp @COMPONENT_PATH@/@COMPONENT_NAME@WidgetController.cpp
+)
+
+set(HEADERS
+./LaserScannerPluginGuiPlugin.h ./LaserScannerPluginWidgetController.h
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@GuiPlugin.h @COMPONENT_PATH@/@COMPONENT_NAME@WidgetController.h
+)
+
+set(GUI_MOC_HDRS ${HEADERS})
+
+set(GUI_UIS
+./LaserScannerPluginWidget.ui
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@Widget.ui
+)
+
+# Add more libraries you depend on here, e.g. ${QT_LIBRARIES}.
+set(COMPONENT_LIBS HokuyoLaserUnit SimpleConfigDialog ${QT_LIBRARIES})
+
+if(ArmarXGui_FOUND)
+	armarx_gui_library(LaserScannerPluginGuiPlugin "${SOURCES}" "${GUI_MOC_HDRS}" "${GUI_UIS}" "" "${COMPONENT_LIBS}")
+endif()
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.cpp b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.cpp
new file mode 100644
index 000000000..c391a0ff6
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.cpp
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \package    RobotAPI::gui-plugins::LaserScannerPluginGuiPlugin
+ * \author     Fabian Paus ( fabian dot paus at kit dot edu )
+ * \date       2017
+ * \copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "LaserScannerPluginGuiPlugin.h"
+
+#include "LaserScannerPluginWidgetController.h"
+
+using namespace armarx;
+
+LaserScannerPluginGuiPlugin::LaserScannerPluginGuiPlugin()
+{
+    addWidget < LaserScannerPluginWidgetController > ();
+}
+
+Q_EXPORT_PLUGIN2(armarx_gui_LaserScannerPluginGuiPlugin, LaserScannerPluginGuiPlugin)
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.h b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.h
new file mode 100644
index 000000000..1a5c4214e
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginGuiPlugin.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \package    RobotAPI::gui-plugins::LaserScannerPlugin
+ * \author     Fabian Paus ( fabian dot paus at kit dot edu )
+ * \date       2017
+ * \copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#ifndef _ARMARX_RobotAPI_LaserScannerPlugin_GuiPlugin_H
+#define _ARMARX_RobotAPI_LaserScannerPlugin_GuiPlugin_H
+
+#include <ArmarXCore/core/system/ImportExportComponent.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
+
+namespace armarx
+{
+    /**
+     * \class LaserScannerPluginGuiPlugin
+     * \ingroup ArmarXGuiPlugins
+     * \brief LaserScannerPluginGuiPlugin brief description
+     *
+     * Detailed description
+     */
+    class ARMARXCOMPONENT_IMPORT_EXPORT LaserScannerPluginGuiPlugin:
+		public armarx::ArmarXGuiPlugin
+    {
+    public:
+        /**
+         * All widgets exposed by this plugin are added in the constructor
+         * via calls to addWidget()
+         */
+        LaserScannerPluginGuiPlugin();
+    };
+}
+
+#endif
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidget.ui b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidget.ui
new file mode 100644
index 000000000..097f7d74a
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidget.ui
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>LaserScannerPluginWidget</class>
+ <widget class="QWidget" name="LaserScannerPluginWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>490</width>
+    <height>379</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>LaserScannerPluginWidget</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <property name="sizeConstraint">
+    <enum>QLayout::SetMinAndMaxSize</enum>
+   </property>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
+     <property name="spacing">
+      <number>6</number>
+     </property>
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Ignored" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="text">
+        <string>Device:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="deviceComboBox"/>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGraphicsView" name="graphicsView">
+     <property name="verticalScrollBarPolicy">
+      <enum>Qt::ScrollBarAlwaysOff</enum>
+     </property>
+     <property name="horizontalScrollBarPolicy">
+      <enum>Qt::ScrollBarAlwaysOff</enum>
+     </property>
+     <property name="resizeAnchor">
+      <enum>QGraphicsView::AnchorViewCenter</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.cpp b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.cpp
new file mode 100644
index 000000000..233f94be9
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.cpp
@@ -0,0 +1,138 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * \package    RobotAPI::gui-plugins::LaserScannerPluginWidgetController
+ * \author     Fabian Paus ( fabian dot paus at kit dot edu )
+ * \date       2017
+ * \copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "LaserScannerPluginWidgetController.h"
+
+#include <QGraphicsView>
+#include <QGraphicsLineItem>
+
+#include <string>
+
+using namespace armarx;
+
+LaserScannerPluginWidgetController::LaserScannerPluginWidgetController()
+{
+    widget.setupUi(getWidget());
+
+    widget.graphicsView->setScene(&scene);
+}
+
+
+LaserScannerPluginWidgetController::~LaserScannerPluginWidgetController()
+{
+
+}
+
+
+void LaserScannerPluginWidgetController::loadSettings(QSettings* settings)
+{
+
+}
+
+void LaserScannerPluginWidgetController::saveSettings(QSettings* settings)
+{
+
+}
+
+
+void LaserScannerPluginWidgetController::onInitComponent()
+{
+    usingProxy(laserScannerUnitName);
+
+    connect(this, SIGNAL(newSensorValuesReported()), this, SLOT(onNewSensorValuesReported()), Qt::QueuedConnection);
+}
+
+
+void LaserScannerPluginWidgetController::onConnectComponent()
+{
+    laserScannerUnit = getProxy<LaserScannerUnitInterfacePrx>(laserScannerUnitName);
+    std::string topicName = laserScannerUnit->getReportTopicName();
+    usingTopic(topicName);
+}
+
+QPointer<QDialog> LaserScannerPluginWidgetController::getConfigDialog(QWidget *parent)
+{
+    if (!dialog)
+    {
+        dialog = new SimpleConfigDialog(parent);
+        dialog->addProxyFinder<LaserScannerUnitInterfacePrx>({"LaserScannerUnit", "", "*LaserUnit"});
+    }
+    return qobject_cast<SimpleConfigDialog*>(dialog);
+}
+
+void LaserScannerPluginWidgetController::configured()
+{
+    if (dialog)
+    {
+        laserScannerUnitName = dialog->getProxyName("LaserScannerUnit");
+    }
+}
+
+void LaserScannerPluginWidgetController::reportSensorValues(const std::string &device, const std::string &name, const LaserScan &newScan, const TimestampBasePtr &timestamp, const Ice::Current &c)
+{
+    {
+        boost::mutex::scoped_lock lock(scanMutex);
+
+        LaserScan& scan = scans[device];
+        // TODO: Do some filtering? aggregation?
+        scan = newScan;
+    }
+
+    emit newSensorValuesReported();
+}
+
+void LaserScannerPluginWidgetController::onNewSensorValuesReported()
+{
+    // TODO: Draw something on the canvas
+
+    QComboBox* deviceBox = widget.deviceComboBox;
+
+    boost::mutex::scoped_lock lock(scanMutex);
+    for (auto& pair : scans)
+    {
+        QString deviceName(QString::fromStdString(pair.first.c_str()));
+        if (deviceBox->findText(deviceName) < 0)
+        {
+            deviceBox->addItem(deviceName);
+        }
+    }
+
+    std::string deviceName(deviceBox->currentText().toUtf8().data());
+
+    QGraphicsView* view = widget.graphicsView;
+    int outerR =std::min(view->width() / 2, view->height() / 2);
+    int r = outerR - 10;
+
+
+    scene.clear();
+    scene.addEllipse(-outerR, -outerR, 2*outerR,2*outerR, QPen(QColor(255,255,255)));
+    scene.addEllipse(-r, -r, 2*r,2*r, QPen(QColor(200,200,200)));
+    auto line = [&](float angle, float d){ scene.addLine(0, 0, std::cos(angle) * d * r, std::sin(angle) * d * r); };
+
+    LaserScan& scan = scans[deviceName];
+    for (LaserScanStep& step : scan)
+    {
+        line(step.angle, step.distance / 30000.0f);
+    }
+
+    view->fitInView(scene.itemsBoundingRect(), Qt::KeepAspectRatio);
+}
diff --git a/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.h b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.h
new file mode 100644
index 000000000..0ee3571d0
--- /dev/null
+++ b/source/RobotAPI/gui-plugins/LaserScannerPlugin/LaserScannerPluginWidgetController.h
@@ -0,0 +1,131 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    RobotAPI::gui-plugins::LaserScannerPluginWidgetController
+ * @author     Fabian Paus ( fabian dot paus at kit dot edu )
+ * @date       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#ifndef _ARMARX_RobotAPI_LaserScannerPlugin_WidgetController_H
+#define _ARMARX_RobotAPI_LaserScannerPlugin_WidgetController_H
+
+#include "ui_LaserScannerPluginWidget.h"
+
+#include <ArmarXCore/core/system/ImportExportComponent.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
+#include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
+#include <RobotAPI/interface/units/LaserScannerUnit.h>
+
+namespace armarx
+{
+    /**
+    \page ArmarXGui-GuiPlugins-LaserScannerPlugin LaserScannerPlugin
+    \brief The LaserScannerPlugin allows visualizing ...
+
+    \image html LaserScannerPlugin.png
+    The user can
+
+    API Documentation \ref LaserScannerPluginWidgetController
+
+    \see LaserScannerPluginGuiPlugin
+    */
+
+    /**
+     * \class LaserScannerPluginWidgetController
+     * \brief LaserScannerPluginWidgetController brief one line description
+     *
+     * Detailed description
+     */
+    class ARMARXCOMPONENT_IMPORT_EXPORT
+        LaserScannerPluginWidgetController:
+    public armarx::ArmarXComponentWidgetController,
+    public armarx::LaserScannerUnitListener
+    {
+        Q_OBJECT
+
+    public:
+        /**
+         * Controller Constructor
+         */
+        explicit LaserScannerPluginWidgetController();
+
+        /**
+         * Controller destructor
+         */
+        virtual ~LaserScannerPluginWidgetController();
+
+        /**
+         * @see ArmarXWidgetController::loadSettings()
+         */
+        virtual void loadSettings(QSettings* settings);
+
+        /**
+         * @see ArmarXWidgetController::saveSettings()
+         */
+        virtual void saveSettings(QSettings* settings);
+
+        /**
+         * Returns the Widget name displayed in the ArmarXGui to create an
+         * instance of this class.
+         */
+        virtual QString getWidgetName() const
+        {
+            return "LaserScannerPlugin";
+        }
+
+        /**
+         * \see armarx::Component::onInitComponent()
+         */
+        virtual void onInitComponent();
+
+        /**
+         * \see armarx::Component::onConnectComponent()
+         */
+        virtual void onConnectComponent();
+
+        QPointer<QDialog> getConfigDialog(QWidget *parent) override;
+
+        void configured() override;
+
+        void reportSensorValues(const std::string & device, const std::string & name,
+                                const LaserScan & scan, const TimestampBasePtr & timestamp,
+                                const Ice::Current & c) override;
+    public slots:
+        void onNewSensorValuesReported();
+
+    signals:
+        void newSensorValuesReported();
+
+    private:
+        /**
+         * Widget Form
+         */
+        Ui::LaserScannerPluginWidget widget;
+        QPointer<SimpleConfigDialog> dialog;
+
+        std::string laserScannerUnitName;
+        LaserScannerUnitInterfacePrx laserScannerUnit;
+
+        Mutex scanMutex;
+        std::unordered_map<std::string, LaserScan> scans;
+
+        QGraphicsScene scene;
+    };
+}
+
+#endif
diff --git a/source/RobotAPI/interface/units/LaserScannerUnit.ice b/source/RobotAPI/interface/units/LaserScannerUnit.ice
index c8ea86f95..113d5331f 100644
--- a/source/RobotAPI/interface/units/LaserScannerUnit.ice
+++ b/source/RobotAPI/interface/units/LaserScannerUnit.ice
@@ -54,6 +54,8 @@ module armarx
 
     interface LaserScannerUnitInterface extends armarx::SensorActorUnitInterface
     {
+        ["cpp:const"]
+        idempotent string getReportTopicName() throws NotInitializedException;
     };
 
     interface LaserScannerUnitListener
-- 
GitLab