From f7ae4d4bc7b541a72143389d96a4462d67df24ff Mon Sep 17 00:00:00 2001
From: Markus Grotz <markus.grotz@kit.edu>
Date: Tue, 31 May 2016 14:16:43 +0200
Subject: [PATCH] moved ViewSelection to RobotAPI

---
 data/RobotAPI/VariantInfo-RobotAPI.xml        |   8 +
 source/RobotAPI/applications/CMakeLists.txt   |   2 +
 .../applications/ViewSelection/CMakeLists.txt |  19 +
 .../ViewSelection/ViewSelectionApp.h          |  54 +++
 .../applications/ViewSelection/main.cpp       |  34 ++
 source/RobotAPI/components/CMakeLists.txt     |   6 +-
 .../components/ViewSelection/CMakeLists.txt   |  29 ++
 .../ViewSelection/ViewSelection.cpp           | 329 ++++++++++++++++++
 .../components/ViewSelection/ViewSelection.h  | 207 +++++++++++
 source/RobotAPI/interface/CMakeLists.txt      |   3 +
 .../components/ViewSelectionInterface.ice     |  75 ++++
 11 files changed, 762 insertions(+), 4 deletions(-)
 create mode 100644 source/RobotAPI/applications/ViewSelection/CMakeLists.txt
 create mode 100644 source/RobotAPI/applications/ViewSelection/ViewSelectionApp.h
 create mode 100644 source/RobotAPI/applications/ViewSelection/main.cpp
 create mode 100644 source/RobotAPI/components/ViewSelection/CMakeLists.txt
 create mode 100644 source/RobotAPI/components/ViewSelection/ViewSelection.cpp
 create mode 100644 source/RobotAPI/components/ViewSelection/ViewSelection.h
 create mode 100755 source/RobotAPI/interface/components/ViewSelectionInterface.ice

diff --git a/data/RobotAPI/VariantInfo-RobotAPI.xml b/data/RobotAPI/VariantInfo-RobotAPI.xml
index d34502bd3..ba6d63e15 100644
--- a/data/RobotAPI/VariantInfo-RobotAPI.xml
+++ b/data/RobotAPI/VariantInfo-RobotAPI.xml
@@ -113,6 +113,14 @@
             <onConnect>remoteRobot.reset(new RemoteRobot(robotStateComponent-&gt;getSynchronizedRobot()));</onConnect>
             <stateMethod header="const VirtualRobot::RobotPtr getRobot() const">return %getContext%-&gt;getRobot();</stateMethod>
         </Proxy>
+        <Proxy include="RobotAPI/interface/components/ViewSelectionInterface.h"
+            humanName="Automatic View Selection"
+            typeName="ViewSelectionInterfacePrx"
+            memberName="viewSelection"
+            getterName="getViewSelection"
+            propertyName="ViewSelectionName"
+            propertyIsOptional="true"
+            propertyDefaultValue="ViewSelection" />
         <Topic include="RobotAPI/interface/visualization/DebugDrawerInterface.h"
             humanName="Debug Drawer Topic"
             typeName="DebugDrawerInterfacePrx"
diff --git a/source/RobotAPI/applications/CMakeLists.txt b/source/RobotAPI/applications/CMakeLists.txt
index c6e30a4ba..736267ef6 100644
--- a/source/RobotAPI/applications/CMakeLists.txt
+++ b/source/RobotAPI/applications/CMakeLists.txt
@@ -20,3 +20,5 @@ add_subdirectory(ForceTorqueUnitSimulation)
 
 add_subdirectory(XsensIMU)
 add_subdirectory(InertialMeasurementUnitObserver)
+
+add_subdirectory(ViewSelection)
diff --git a/source/RobotAPI/applications/ViewSelection/CMakeLists.txt b/source/RobotAPI/applications/ViewSelection/CMakeLists.txt
new file mode 100644
index 000000000..e9617c086
--- /dev/null
+++ b/source/RobotAPI/applications/ViewSelection/CMakeLists.txt
@@ -0,0 +1,19 @@
+armarx_component_set_name("ViewSelectionApp")
+
+find_package(Eigen3 QUIET)
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+if(Eigen3_FOUND)
+    include_directories(${Eigen3_INCLUDE_DIR})
+endif()
+
+
+set(COMPONENT_LIBS
+    ViewSelection
+    RobotAPIInterfaces RobotAPICore
+    ArmarXCoreInterfaces ArmarXCore ArmarXCoreStatechart ArmarXCoreObservers
+)
+
+
+set(EXE_SOURCE main.cpp ViewSelectionApp.h)
+
+armarx_add_component_executable("${EXE_SOURCE}")
diff --git a/source/RobotAPI/applications/ViewSelection/ViewSelectionApp.h b/source/RobotAPI/applications/ViewSelection/ViewSelectionApp.h
new file mode 100644
index 000000000..f26a56822
--- /dev/null
+++ b/source/RobotAPI/applications/ViewSelection/ViewSelectionApp.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2015-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    RobotComponents::application::ViewSelection
+ * @author     David Schiebener (schiebener qt kit dot edu)
+ * @date       2015
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#ifndef _ARMARX_APPLICATION_RobotComponents_ViewSelection_H
+#define _ARMARX_APPLICATION_RobotComponents_ViewSelection_H
+
+
+#include <ArmarXCore/core/application/Application.h>
+#include <RobotAPI/components/ViewSelection/ViewSelection.h>
+
+namespace armarx
+{
+    /**
+     * @class ViewSelectionApp
+     * @brief A brief description
+     *
+     * Detailed Description
+     */
+    class ViewSelectionApp :
+        virtual public armarx::Application
+    {
+        /**
+         * @see armarx::Application::setup()
+         */
+        void setup(const ManagedIceObjectRegistryInterfacePtr& registry,
+                   Ice::PropertiesPtr properties)
+        {
+            registry->addObject(Component::create<ViewSelection>(properties));
+        }
+    };
+}
+
+#endif
diff --git a/source/RobotAPI/applications/ViewSelection/main.cpp b/source/RobotAPI/applications/ViewSelection/main.cpp
new file mode 100644
index 000000000..01e91acc5
--- /dev/null
+++ b/source/RobotAPI/applications/ViewSelection/main.cpp
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2015-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    RobotComponents::application::ViewSelection
+ * @author     David Schiebener (schiebener qt kit dot edu)
+ * @date       2015
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "ViewSelectionApp.h"
+#include <ArmarXCore/core/logging/Logging.h>
+
+int main(int argc, char* argv[])
+{
+    armarx::ApplicationPtr app = armarx::Application::createInstance < armarx::ViewSelectionApp > ();
+    app->setName("ViewSelection");
+
+    return app->main(argc, argv);
+}
diff --git a/source/RobotAPI/components/CMakeLists.txt b/source/RobotAPI/components/CMakeLists.txt
index b596e7006..bf391c4c6 100644
--- a/source/RobotAPI/components/CMakeLists.txt
+++ b/source/RobotAPI/components/CMakeLists.txt
@@ -1,7 +1,5 @@
-
 add_subdirectory(units)
 add_subdirectory(DebugDrawer)
 add_subdirectory(RobotState)
-
-
-add_subdirectory(EarlyVisionGraph)
\ No newline at end of file
+add_subdirectory(EarlyVisionGraph)
+add_subdirectory(ViewSelection)
diff --git a/source/RobotAPI/components/ViewSelection/CMakeLists.txt b/source/RobotAPI/components/ViewSelection/CMakeLists.txt
new file mode 100644
index 000000000..3fb96c045
--- /dev/null
+++ b/source/RobotAPI/components/ViewSelection/CMakeLists.txt
@@ -0,0 +1,29 @@
+armarx_component_set_name("ViewSelection")
+
+
+find_package(Eigen3 QUIET)
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+if(Eigen3_FOUND)
+    include_directories(${Eigen3_INCLUDE_DIR})
+endif()
+
+
+set(COMPONENT_LIBS
+    RobotAPIInterfaces RobotAPICore EarlyVisionGraph
+    ArmarXCoreInterfaces ArmarXCore ArmarXCoreStatechart ArmarXCoreObservers
+    ${Simox_LIBRARIES}
+)
+
+set(SOURCES
+./ViewSelection.cpp
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.cpp
+)
+set(HEADERS
+./ViewSelection.h
+#@TEMPLATE_LINE@@COMPONENT_PATH@/@COMPONENT_NAME@.h
+)
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+
+# add unit tests
+#add_subdirectory(test)
diff --git a/source/RobotAPI/components/ViewSelection/ViewSelection.cpp b/source/RobotAPI/components/ViewSelection/ViewSelection.cpp
new file mode 100644
index 000000000..3ab494165
--- /dev/null
+++ b/source/RobotAPI/components/ViewSelection/ViewSelection.cpp
@@ -0,0 +1,329 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2015-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    RobotComponents::ViewSelection
+ * @author     David Schiebener (schiebener at kit dot edu)
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2015
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "ViewSelection.h"
+
+#include <ArmarXCore/core/system/ArmarXDataPath.h>
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
+
+#include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h>
+
+
+using namespace armarx;
+
+
+void ViewSelection::onInitComponent()
+{
+    usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
+    usingProxy(getProperty<std::string>("HeadIKUnitName").getValue());
+
+    offeringTopic("DebugDrawerUpdates");
+
+    headIKKinematicChainName = getProperty<std::string>("HeadIKKinematicChainName").getValue();
+    headFrameName = getProperty<std::string>("HeadFrameName").getValue();
+    cameraFrameName = getProperty<std::string>("CameraFrameName").getValue();
+    drawViewDirection = getProperty<bool>("VisualizeViewDirection").getValue();
+
+    std::string graphFileName = "RobotComponents/ViewSelection/graph40k.gra";
+
+    armarx::CMakePackageFinder finder("RobotComponents");
+    ArmarXDataPath::addDataPaths(finder.getDataDir());
+
+    if (ArmarXDataPath::getAbsolutePath(graphFileName, graphFileName))
+    {
+        visibilityMaskGraph = new CIntensityGraph(graphFileName);
+        TNodeList* nodes = visibilityMaskGraph->getNodes();
+        const float maxOverallHeadTiltAngle = getProperty<float>("MaxOverallHeadTiltAngle").getValue();
+        const float borderAreaAngle = 10.0f;
+        const float centralAngle = getProperty<float>("CentralHeadTiltAngle").getValue();
+
+        for (size_t i = 0; i < nodes->size(); i++)
+        {
+            CIntensityNode* node = (CIntensityNode*) nodes->at(i);
+
+            if (fabs(node->getPosition().fPhi - centralAngle) < maxOverallHeadTiltAngle - borderAreaAngle)
+            {
+                node->setIntensity(1.0f);
+            }
+            else if (fabs(node->getPosition().fPhi - centralAngle) < maxOverallHeadTiltAngle)
+            {
+                node->setIntensity(1.0f - (fabs(node->getPosition().fPhi - centralAngle) - (maxOverallHeadTiltAngle - borderAreaAngle)) / borderAreaAngle);
+            }
+            else
+            {
+                node->setIntensity(0.0f);
+            }
+        }
+    }
+    else
+    {
+        ARMARX_ERROR << "Could not find required1 graph file";
+        handleExceptions();
+    }
+
+    sleepingTimeBetweenViewDirectionChanges = getProperty<int>("SleepingTimeBetweenViewDirectionChanges").getValue();
+    doAutomaticViewSelection = getProperty<bool>("ActiveAtStartup").getValue();
+
+    timeOfLastViewChange = IceUtil::Time::now();
+
+    // this is robot model specific: offset from the used head coordinate system to the actual
+    // head center where the eyes are assumed to be located. Here it is correct for ARMAR-III
+    offsetToHeadCenter << 0, 0, 150;
+
+    processorTask = new PeriodicTask<ViewSelection>(this, &ViewSelection::process, 30);
+    processorTask->setDelayWarningTolerance(sleepingTimeBetweenViewDirectionChanges + 100);
+}
+
+
+void ViewSelection::onConnectComponent()
+{
+    robotStateComponent = getProxy<RobotStateComponentInterfacePrx>(getProperty<std::string>("RobotStateComponentName").getValue());
+
+    headIKUnitProxy = getProxy<HeadIKUnitInterfacePrx>(getProperty<std::string>("HeadIKUnitName").getValue());
+    headIKUnitProxy->request();
+
+    drawer = getTopic<DebugDrawerInterfacePrx>("DebugDrawerUpdates");
+
+    processorTask->start();
+}
+
+
+void ViewSelection::onDisconnectComponent()
+{
+    processorTask->stop();
+
+    if (drawer)
+    {
+        drawer->removeArrowDebugLayerVisu("HeadRealViewDirection");
+    }
+
+    try
+    {
+        headIKUnitProxy->release();
+    }
+    catch (...)
+    {
+        ARMARX_WARNING_S << "An exception occured during onDisconnectComponent()";
+        handleExceptions();
+    }
+}
+
+
+void ViewSelection::onExitComponent()
+{
+    delete visibilityMaskGraph;
+}
+
+
+ViewTargetBasePtr ViewSelection::nextAutomaticViewTarget()
+{
+    SharedRobotInterfacePrx robotPrx = robotStateComponent->getSynchronizedRobot();
+    TNodeList* visibilityMaskGraphNodes = visibilityMaskGraph->getNodes();
+
+    // find the direction with highest saliency
+    int maxIndex = -1;
+    float maxSaliency = 0;
+    for (size_t i = 0; i < visibilityMaskGraphNodes->size(); i++)
+    {
+        float saliency = 0.0f;
+        for (const auto & p : saliencyMaps)
+        {
+            saliency += p.second[i];
+        }
+
+        CIntensityNode* visibilityNode = (CIntensityNode*) visibilityMaskGraphNodes->at(i);
+        saliency *= visibilityNode->getIntensity();
+
+        if (saliency > maxSaliency)
+        {
+            maxSaliency = saliency;
+            maxIndex = i;
+        }
+    }
+
+    ARMARX_DEBUG << "Highest saliency: " << maxSaliency;
+
+    // select a new view if saliency is bigger than threshold (which converges towards 0 over time)
+    int timeSinceLastViewChange = (IceUtil::Time::now() - timeOfLastViewChange).toMilliSeconds();
+    float saliencyThreshold = 0;
+
+    if (timeSinceLastViewChange > 0)
+    {
+        saliencyThreshold = 2.0f * sleepingTimeBetweenViewDirectionChanges / timeSinceLastViewChange;
+    }
+
+    if (maxSaliency > saliencyThreshold)
+    {
+        Eigen::Vector3f target;
+        MathTools::convert(visibilityMaskGraphNodes->at(maxIndex)->getPosition(), target);
+        const float distanceFactor = 1500;
+        target = distanceFactor * target + offsetToHeadCenter;
+        FramedPositionPtr viewTargetPositionPtr = new FramedPosition(target, headFrameName, robotPrx->getName());
+
+        ViewTargetBasePtr viewTarget = new ViewTargetBase();
+        viewTarget->priority = armarx::DEFAULT_VIEWTARGET_PRIORITY; // *  maxSaliency;
+        viewTarget->timeAdded = new TimestampVariant(IceUtil::Time::now());
+        viewTarget->target = viewTargetPositionPtr;
+        viewTarget->duration = 0;
+
+        return viewTarget;
+    }
+
+    return nullptr;
+}
+
+
+
+void ViewSelection::process()
+{
+    ViewTargetBasePtr viewTarget;
+
+    if (doAutomaticViewSelection)
+    {
+        viewTarget = nextAutomaticViewTarget();
+    }
+
+    if (!manualViewTargets.empty())
+    {
+        ScopedLock lock(manualViewTargetsMutex);
+
+        ViewTargetBasePtr manualViewTarget = manualViewTargets.top();
+
+        CompareViewTargets c;
+
+        if (!viewTarget)
+        {
+            viewTarget = manualViewTarget;
+            manualViewTargets.pop();
+        }
+        else if (c(viewTarget, manualViewTarget))
+        {
+            viewTarget = manualViewTarget;
+            manualViewTargets.pop();
+        }
+    }
+
+    if (viewTarget)
+    {
+        SharedRobotInterfacePrx robotPrx = robotStateComponent->getSynchronizedRobot();
+        FramedPositionPtr viewTargetPositionPtr = new FramedPosition(FramedPositionPtr::dynamicCast(viewTarget->target)->toEigen(), viewTarget->target->frame, robotPrx->getName());
+
+        if (drawer && robotPrx->hasRobotNode("Cameras") && drawViewDirection)
+        {
+            float arrowLength = 1500.0f;
+            Vector3Ptr startPos = new Vector3(FramedPosePtr::dynamicCast(robotPrx->getRobotNode("Cameras")->getGlobalPose())->toEigen());
+            FramedDirectionPtr currentDirection = new FramedDirection(Eigen::Vector3f(1, 0, 0), "Cameras", robotPrx->getName());
+            drawer->setArrowDebugLayerVisu("CurrentHeadViewDirection", startPos, currentDirection->toGlobal(robotPrx), DrawColor {0, 0.5, 0.5, 0.1}, arrowLength, 5);
+            Eigen::Vector3f plannedDirectionEigen = viewTargetPositionPtr->toGlobalEigen(robotPrx) - startPos->toEigen();
+            Vector3Ptr plannedDirection = new Vector3(plannedDirectionEigen);
+            drawer->setArrowDebugLayerVisu("PlannedHeadViewDirection", startPos, plannedDirection, DrawColor {0.5, 0.5, 0, 0.1}, arrowLength, 5);
+        }
+
+        ARMARX_INFO << "Looking at target " << viewTargetPositionPtr->output();
+        headIKUnitProxy->setHeadTarget(headIKKinematicChainName, viewTargetPositionPtr);
+
+        timeOfLastViewChange = IceUtil::Time::now();
+
+
+        float duration = viewTarget->duration;
+        if (!viewTarget->duration)
+        {
+            duration = sleepingTimeBetweenViewDirectionChanges;
+        }
+
+
+        boost::this_thread::sleep(boost::posix_time::milliseconds(duration));
+    }
+    else
+    {
+        boost::this_thread::sleep(boost::posix_time::milliseconds(5));
+    }
+}
+
+
+
+void ViewSelection::addManualViewTarget(const FramedPositionBasePtr& target, const Ice::Current& c)
+{
+    boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+    //SharedRobotInterfacePrx sharedRobotInterface = robotStateComponent->getRobotSnapshot();
+
+    ViewTargetBasePtr viewTarget = new ViewTargetBase();
+    viewTarget->priority = armarx::DEFAULT_VIEWTARGET_PRIORITY + 1;
+    viewTarget->timeAdded = new TimestampVariant(IceUtil::Time::now());
+    viewTarget->target = target;
+    viewTarget->duration = 0;
+
+    manualViewTargets.push(viewTarget);
+}
+
+void ViewSelection::clearManualViewTargets(const Ice::Current& c)
+{
+    boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+    while (!manualViewTargets.empty())
+    {
+        manualViewTargets.pop();
+    }
+
+    // std::priority_queue<ViewTargetBasePtr, vector<ViewTargetBasePtr>, CompareViewTargets> temp;
+    // manualViewTargets.swap(temp);
+}
+
+ViewTargetList ViewSelection::getManualViewTargets(const Ice::Current& c)
+{
+    boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+    ViewTargetList result;
+
+    std::priority_queue<ViewTargetBasePtr, vector<ViewTargetBasePtr>, CompareViewTargets> temp(manualViewTargets);
+
+    while (!temp.empty())
+    {
+        result.push_back(temp.top());
+
+        temp.pop();
+    }
+
+    return result;
+}
+
+
+
+void armarx::ViewSelection::updateSaliencyMap(const string& name, const FloatSequence& map, const Ice::Current&)
+{
+    boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+    saliencyMaps[name] = map;
+}
+
+
+PropertyDefinitionsPtr ViewSelection::createPropertyDefinitions()
+{
+    return PropertyDefinitionsPtr(new ViewSelectionPropertyDefinitions(getConfigIdentifier()));
+}
+
+
+
diff --git a/source/RobotAPI/components/ViewSelection/ViewSelection.h b/source/RobotAPI/components/ViewSelection/ViewSelection.h
new file mode 100644
index 000000000..ce8977b57
--- /dev/null
+++ b/source/RobotAPI/components/ViewSelection/ViewSelection.h
@@ -0,0 +1,207 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2015-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * 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    RobotComponents::ViewSelection
+ * @author     David Schiebener (schiebener at kit dot edu)
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2015
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#ifndef _ARMARX_COMPONENT_RobotComponents_ViewSelection_H
+#define _ARMARX_COMPONENT_RobotComponents_ViewSelection_H
+
+
+#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/observers/variant/TimestampVariant.h>
+#include <ArmarXCore/core/services/tasks/RunningTask.h>
+
+#include <RobotAPI/libraries/core/Pose.h>
+#include <RobotAPI/interface/core/RobotState.h>
+
+#include <RobotAPI/interface/components/ViewSelectionInterface.h>
+
+#include <RobotAPI/components/units/HeadIKUnit.h>
+
+#include <RobotAPI/components/EarlyVisionGraph/IntensityGraph.h>
+#include <RobotAPI/components/EarlyVisionGraph/GraphPyramidLookupTable.h>
+#include <RobotAPI/components/EarlyVisionGraph/MathTools.h>
+
+
+#include <Eigen/Geometry>
+
+
+#include <queue>
+
+namespace armarx
+{
+
+    struct CompareViewTargets
+    {
+        bool operator()(ViewTargetBasePtr const& t1, ViewTargetBasePtr const& t2)
+        {
+            if (t1->priority == t2->priority)
+            {
+                return t1->timeAdded->timestamp < t2->timeAdded->timestamp;
+
+            }
+            return t1->priority < t2->priority;
+        }
+    };
+
+
+    /**
+     * @class ViewSelectionPropertyDefinitions
+     * @brief
+     */
+    class ViewSelectionPropertyDefinitions:
+        public ComponentPropertyDefinitions
+    {
+    public:
+        ViewSelectionPropertyDefinitions(std::string prefix):
+            ComponentPropertyDefinitions(prefix)
+        {
+            defineOptionalProperty<std::string>("RobotStateComponentName", "RobotStateComponent", "Name of the robot state component that should be used");
+            defineOptionalProperty<std::string>("HeadIKUnitName", "HeadIKUnit", "Name of the head IK unit component that should be used");
+            defineOptionalProperty<std::string>("HeadIKKinematicChainName", "IKVirtualGaze", "Name of the kinematic chain for the head IK");
+            defineOptionalProperty<std::string>("HeadFrameName", "Head Base", "Name of the frame of the head base in the robot model");
+            defineOptionalProperty<std::string>("CameraFrameName", "VirtualCentralGaze", "Name of the frame of the head base in the robot model");
+            defineOptionalProperty<int>("SleepingTimeBetweenViewDirectionChanges", 2500, "Time between two view changes, to keep the head looking into one direction for a while (in ms)");
+            defineOptionalProperty<bool>("ActiveAtStartup", true, "Decide whether the automatic view selection will be activated (can be changed via the proxy during runtime)");
+            defineOptionalProperty<bool>("VisualizeViewDirection", false, "Draw view ray on DebugLayer.");
+            defineOptionalProperty<float>("MaxOverallHeadTiltAngle", 55.0f, "Maximal angle the head and eyes can look down (in degrees)");
+            defineOptionalProperty<float>("CentralHeadTiltAngle", 110.0f, "Defines the height direction that will be considered 'central' in the reachable area of the head (in degrees). Default is looking 20 degrees downwards");
+            defineOptionalProperty<float>("ProbabilityToLookForALostObject", 0.03f, "Probability that one of the objects that have been seen but could later not been localized again will be included in the view selection");
+        }
+    };
+
+    /**
+     * @defgroup Component-ViewSelection ViewSelection
+     * @ingroup RobotComponents-Components
+     * @brief The ViewSelection component controls the head of the robot with inverse kinematics based on the uncertainty
+     * of the current requested object locations.
+     * The uncertainty of objects grow based on their motion model and the timed passed since the last localization.
+     * It can be activated or deactivated with the Ice interface and given manual target positions to look at.
+     */
+
+    /**
+     * @ingroup Component-ViewSelection
+     * @brief The ViewSelection class
+     */
+    class ViewSelection :
+        virtual public Component,
+        virtual public ViewSelectionInterface
+    {
+    public:
+        /**
+         * @see armarx::ManagedIceObject::getDefaultName()
+         */
+        virtual std::string getDefaultName() const
+        {
+            return "ViewSelection";
+        }
+
+    protected:
+        /**
+         * @see armarx::ManagedIceObject::onInitComponent()
+         */
+        virtual void onInitComponent();
+
+        /**
+         * @see armarx::ManagedIceObject::onConnectComponent()
+         */
+        virtual void onConnectComponent();
+
+        /**
+         * @see armarx::ManagedIceObject::onDisconnectComponent()
+         */
+        virtual void onDisconnectComponent();
+
+        /**
+         * @see armarx::ManagedIceObject::onExitComponent()
+         */
+        virtual void onExitComponent();
+
+        /**
+         * @see PropertyUser::createPropertyDefinitions()
+         */
+        virtual PropertyDefinitionsPtr createPropertyDefinitions();
+
+        virtual void addManualViewTarget(const FramedPositionBasePtr& target, const Ice::Current& c = Ice::Current());
+
+        virtual void clearManualViewTargets(const Ice::Current& c = Ice::Current());
+
+        virtual ViewTargetList getManualViewTargets(const Ice::Current& c = Ice::Current());
+
+        virtual void activateAutomaticViewSelection(const Ice::Current& c = Ice::Current())
+        {
+            boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+            ARMARX_INFO << "activating automatic view selection";
+            doAutomaticViewSelection = true;
+        }
+
+        virtual void deactivateAutomaticViewSelection(const Ice::Current& c = Ice::Current())
+        {
+            boost::mutex::scoped_lock lock(manualViewTargetsMutex);
+
+            ARMARX_INFO << "DEactivating automatic view selection";
+            doAutomaticViewSelection = false;
+        }
+
+        void updateSaliencyMap(const string& name, const FloatSequence& map, const Ice::Current& c = ::Ice::Current());
+
+    private:
+
+        void process();
+
+        ViewTargetBasePtr nextAutomaticViewTarget();
+
+        armarx::PeriodicTask<ViewSelection>::pointer_type processorTask;
+
+        RobotStateComponentInterfacePrx robotStateComponent;
+        HeadIKUnitInterfacePrx headIKUnitProxy;
+        DebugDrawerInterfacePrx drawer;
+
+        std::string headIKKinematicChainName;
+        std::string headFrameName;
+        std::string cameraFrameName;
+
+        CIntensityGraph* visibilityMaskGraph;
+
+        float sleepingTimeBetweenViewDirectionChanges;
+        IceUtil::Time timeOfLastViewChange;
+
+        bool drawViewDirection;
+
+        armarx::Mutex manualViewTargetsMutex;
+        std::priority_queue<ViewTargetBasePtr, vector<ViewTargetBasePtr>, CompareViewTargets> manualViewTargets;
+
+        bool doAutomaticViewSelection;
+
+        Eigen::Vector3f offsetToHeadCenter;
+
+
+        std::map<std::string, std::vector<float>> saliencyMaps;
+
+    };
+
+
+}
+
+#endif
diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt
index 250737dce..1bd39e90f 100644
--- a/source/RobotAPI/interface/CMakeLists.txt
+++ b/source/RobotAPI/interface/CMakeLists.txt
@@ -36,6 +36,9 @@ set(SLICE_FILES
     units/UnitInterface.ice
     units/ATINetFTUnit.ice
 
+
+    components/ViewSelectionInterface.ice
+
     visualization/DebugDrawerInterface.ice
 )
     #core/RobotIK.ice
diff --git a/source/RobotAPI/interface/components/ViewSelectionInterface.ice b/source/RobotAPI/interface/components/ViewSelectionInterface.ice
new file mode 100755
index 000000000..7521a30c8
--- /dev/null
+++ b/source/RobotAPI/interface/components/ViewSelectionInterface.ice
@@ -0,0 +1,75 @@
+/**
+* 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    RobotComponents
+* @author     David Schiebener (schiebener at kit dot edu)
+* @author     Markus Grotz ( markus dot grotz at kit dot edu )
+* @copyright  2015 Humanoids Group, H2T, KIT
+* @license    http://www.gnu.org/licenses/gpl-2.0.txt
+*             GNU General Public License
+*/
+
+#ifndef _ROBOTCOMPONENTS_COMPONENT_ViewSelection_SLICE_
+#define _ROBOTCOMPONENTS_COMPONENT_ViewSelection_SLICE_
+
+#include <RobotAPI/interface/core/PoseBase.ice>
+#include <RobotAPI/interface/core/FramedPoseBase.ice>
+
+#include <ArmarXCore/interface/observers/Timestamp.ice>
+#include <ArmarXCore/interface/core/BasicTypes.ice>
+
+module armarx
+{
+
+    const int DEFAULT_VIEWTARGET_PRIORITY = 50;
+
+
+    ["cpp:virtual"]
+    class ViewTargetBase
+    {
+        armarx::FramedPositionBase target;
+
+        TimestampBase validUntil;
+
+        TimestampBase timeAdded;
+
+        float duration;
+
+        int priority;
+
+        string source;
+    };
+
+    sequence<ViewTargetBase> ViewTargetList;
+
+    interface ViewSelectionInterface
+    {
+        void addManualViewTarget(armarx::FramedPositionBase target);
+        void clearManualViewTargets();
+        ViewTargetList getManualViewTargets();
+
+        void activateAutomaticViewSelection();
+        void deactivateAutomaticViewSelection();
+
+        void updateSaliencyMap(string name, FloatSequence map);
+    };
+
+
+};
+
+#endif
+
+
+
-- 
GitLab