From 3538226ff01f346f516bd09f33b10ab9deb6fc0a Mon Sep 17 00:00:00 2001
From: Nikolaus Vahrenkamp <vahrenkamp@kit.edu>
Date: Fri, 6 Mar 2015 17:30:12 +0100
Subject: [PATCH] Added robot visualization to debug drawer

---
 .../DebugDrawer/DebugDrawerComponent.cpp      | 229 ++++++++++++++++++
 .../DebugDrawer/DebugDrawerComponent.h        |  43 +++-
 .../visualization/DebugDrawerInterface.ice    |  20 ++
 3 files changed, 291 insertions(+), 1 deletion(-)

diff --git a/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.cpp b/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.cpp
index f0df39894..b08c2f3fd 100644
--- a/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.cpp
+++ b/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.cpp
@@ -25,6 +25,7 @@
 #include "DebugDrawerComponent.h"
 
 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
+#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualization.h>
 #include <Inventor/nodes/SoUnits.h>
 #include <Inventor/nodes/SoCube.h>
 #include <Inventor/nodes/SoMaterial.h>
@@ -36,6 +37,8 @@
 #include <Inventor/nodes/SoComplexity.h>
 #include <Inventor/nodes/SoCoordinate3.h>
 #include <Inventor/nodes/SoPointSet.h>
+#include <Core/core/system/ArmarXDataPath.h>
+#include <Core/core/system/cmake/CMakePackageFinder.h>
 
 using namespace VirtualRobot;
 
@@ -400,7 +403,126 @@ void DebugDrawerComponent::drawArrow(const DebugDrawerComponent::ArrowData &d)
 
     layer.addedArrowVisualizations[d.name] = sep;
     layer.mainNode->addChild(sep);
+}
+
+void DebugDrawerComponent::drawRobot(const DebugDrawerComponent::RobotData &d)
+{
+    ScopedRecursiveLockPtr l = getScopedLock();
 
+    auto& layer=requestLayer(d.layerName);
+
+    if (!d.active)
+    {
+        ARMARX_INFO << "Removing robot " << d.name;
+        removeRobot(d.layerName,d.name);
+        return;
+    }
+    // load or get robot
+    RobotPtr rob = requestRobot(d);
+    if (!rob)
+    {
+        ARMARX_ERROR << deactivateSpam() << "Could not determine robot " << d.name << " at layer " << d.layerName;
+        return;
+    }
+
+    if (d.updatePose)
+    {
+        rob->setGlobalPose(d.globalPose);
+    }
+    if (d.updateConfig)
+    {
+        rob->setJointValues(d.configuration);
+    }
+    if (d.updateColor)
+    {
+        SoSeparator *sep = layer.addedRobotVisualizations[d.name];
+        if (!sep || sep->getNumChildren()<2)
+        {
+            ARMARX_ERROR << "Internal robot layer error1";
+            return;
+        }
+
+        SoMaterial* m = dynamic_cast<SoMaterial*>(sep->getChild(0));
+        if (!m)
+        {
+            ARMARX_ERROR << "Internal robot layer error2";
+            return;
+        }
+        if (d.color.isNone())
+        {
+            m->setOverride(false);
+        } else
+        {
+            m->diffuseColor = SbColor(d.color.r,d.color.g,d.color.b);
+            m->ambientColor = SbColor(0,0,0);
+            m->transparency = std::max(0.0f,d.color.transparency);
+            m->setOverride(true);
+        }
+    }
+}
+
+VirtualRobot::RobotPtr DebugDrawerComponent::requestRobot(const DebugDrawerComponent::RobotData &d)
+{
+    ScopedRecursiveLockPtr l = getScopedLock();
+
+    auto& layer=requestLayer(d.layerName);
+    std::string entryName = "__" + d.layerName + "__" + d.name + "__";
+
+    if (activeRobots.find(entryName) != activeRobots.end())
+        return activeRobots[entryName];
+
+    //ARMARX_INFO << "Loading robot " << entryName;
+    VirtualRobot::RobotPtr result;
+
+    if (d.robotFile.empty())
+    {
+        ARMARX_INFO << deactivateSpam() << "No robot defined for layer " << d.layerName << ", with name " << d.name;
+        return result;
+    }
+
+    if (!d.armarxProject.empty())
+    {
+        ARMARX_INFO << "Adding to datapaths of " << d.armarxProject;
+        armarx::CMakePackageFinder finder(d.armarxProject);
+        if (!finder.packageFound())
+        {
+            ARMARX_WARNING << "ArmarX Package " << d.armarxProject << " has not been found!";
+        } else
+        {
+            ARMARX_INFO << "Adding to datapaths: " << finder.getDataDir();
+            armarx::ArmarXDataPath::addDataPaths(finder.getDataDir());
+        }
+    }
+
+    // load robot
+    std::string filename = d.robotFile;
+    ArmarXDataPath::getAbsolutePath(filename,filename);
+    ARMARX_INFO << "Loading robot from " << filename;
+    try
+    {
+        result = RobotIO::loadRobot(filename);
+    } catch (...)
+    {
+        ARMARX_IMPORTANT << "Robot loading failed, file:" << filename;
+        return result;
+    }
+    ARMARX_INFO << "Loaded robot";
+
+    SoSeparator *sep = new SoSeparator;
+    layer.mainNode->addChild(sep);
+
+    SoMaterial *m = new SoMaterial;
+    m->setOverride(false);
+    sep->addChild(m);
+
+    boost::shared_ptr<CoinVisualization> robVisu = result->getVisualization<CoinVisualization>(VirtualRobot::SceneObject::Full);
+    SoNode *sepRob = robVisu->getCoinVisualization();
+    sep->addChild(sepRob);
+
+    activeRobots[entryName] = result;
+    layer.addedRobotVisualizations[d.name] = sep;
+
+    return result;
 }
 
 void DebugDrawerComponent::removeLine(const std::string& layerName, const std::string &name)
@@ -522,6 +644,30 @@ void DebugDrawerComponent::removeArrow(const std::string &layerName, const std::
     layer.addedArrowVisualizations.erase(name);
 }
 
+void DebugDrawerComponent::removeRobot(const std::string &layerName, const std::string &name)
+{
+    ScopedRecursiveLockPtr l = getScopedLock();
+
+    // process active robots
+    std::string entryName = "__" + layerName + "__" + name + "__";
+    if (activeRobots.find(entryName) != activeRobots.end())
+        activeRobots.erase(entryName);
+
+    // process visualizations
+    if(!hasLayer(layerName))
+    {
+        return;
+    }
+    auto& layer=layers.at(layerName);
+    if(layer.addedRobotVisualizations.find(name) == layer.addedRobotVisualizations.end())
+    {
+        return;
+    }
+
+    layer.mainNode->removeChild(layer.addedRobotVisualizations[name]);
+    layer.addedRobotVisualizations.erase(name);
+}
+
 void DebugDrawerComponent::removeCoordSystem(const std::string& layerName, const std::string &name)
 {
     ScopedRecursiveLockPtr l = getScopedLock();
@@ -923,6 +1069,83 @@ void DebugDrawerComponent::removeArrowDebugLayerVisu(const std::string &arrowNam
     removeArrowVisu(DEBUG_LAYER_NAME, arrowName);
 }
 
+void DebugDrawerComponent::setRobotVisu(const std::string &layerName, const std::string &robotName, const std::string &robotFile, const std::string &armarxProject, const Ice::Current &)
+{
+    ScopedRecursiveLockPtr l = getScopedDataLock();
+    std::string entryName = "__" + layerName + "__" + robotName + "__";
+    RobotData &d = accumulatedUpdateData.robots[entryName];
+
+    d.robotFile = robotFile;
+    d.armarxProject = armarxProject;
+
+    d.layerName = layerName;
+    d.name = robotName;
+    d.active = true;
+}
+
+void DebugDrawerComponent::updateRobotPose(const std::string &layerName, const std::string &robotName, const PoseBasePtr &globalPose, const Ice::Current &)
+{
+    ScopedRecursiveLockPtr l = getScopedDataLock();
+    std::string entryName = "__" + layerName + "__" + robotName + "__";
+    RobotData &d = accumulatedUpdateData.robots[entryName];
+
+    // update data
+    d.update = true;
+    d.updatePose = true;
+    d.globalPose = PosePtr::dynamicCast(globalPose)->toEigen();
+
+    d.layerName = layerName;
+    d.name = robotName;
+    d.active = true;
+}
+
+void DebugDrawerComponent::updateRobotConfig(const std::string &layerName, const std::string &robotName, const std::map<std::string, float> &configuration, const Ice::Current &)
+{
+    ScopedRecursiveLockPtr l = getScopedDataLock();
+    std::string entryName = "__" + layerName + "__" + robotName + "__";
+    RobotData &d = accumulatedUpdateData.robots[entryName];
+
+    // update data
+    d.update = true;
+    d.updateConfig = true;
+    d.layerName = layerName;
+    d.name = robotName;
+    for(auto& it : configuration)
+    {
+        d.configuration[it.first] = it.second;
+    }
+    d.active = true;
+}
+
+void DebugDrawerComponent::updateRobotColor(const std::string &layerName, const std::string &robotName, const DrawColor &c, const Ice::Current &)
+{
+    ScopedRecursiveLockPtr l = getScopedDataLock();
+    std::string entryName = "__" + layerName + "__" + robotName + "__";
+    RobotData &d = accumulatedUpdateData.robots[entryName];
+
+    // update data
+    d.update = true;
+    d.updateColor = true;
+    d.layerName = layerName;
+    d.name = robotName;
+    if (c.a == 0 && c.b == 0 && c.r == 0 && c.g == 0)
+        d.color = VirtualRobot::VisualizationFactory::Color::None();
+    else
+        d.color = VirtualRobot::VisualizationFactory::Color(c.r, c.g, c.b, 1 - c.a);
+
+    d.active = true;
+}
+
+void DebugDrawerComponent::removeRobotVisu(const std::string &layerName, const std::string &robotName, const Ice::Current &)
+{
+    ScopedRecursiveLockPtr l = getScopedDataLock();
+    std::string entryName = "__" + layerName + "__" + robotName + "__";
+    RobotData &d = accumulatedUpdateData.robots[entryName];
+    d.layerName = layerName;
+    d.name = robotName;
+    d.active = false;
+}
+
 //todo: in some rare cases the mutex3D lock does not work and results in a broken coin timer setup. No updates of the scene will be drawn in this case
 // -> check for a qt-thread solution
 void DebugDrawerComponent::clearLayer(const std::string &layerName, const Ice::Current &)
@@ -1055,6 +1278,12 @@ void DebugDrawerComponent::updateVisualization()
     }
     accumulatedUpdateData.arrows.clear();
 
+    for (auto i = accumulatedUpdateData.robots.begin(); i != accumulatedUpdateData.robots.end(); i++)
+    {
+        drawRobot(i->second);
+    }
+    accumulatedUpdateData.robots.clear();
+
 }
 
 bool DebugDrawerComponent::hasLayer(const std::string& layerName, const ::Ice::Current&)
diff --git a/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.h b/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.h
index f8cbc853b..004998149 100644
--- a/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.h
+++ b/source/RobotAPI/components/DebugDrawer/DebugDrawerComponent.h
@@ -181,6 +181,25 @@ public:
     virtual void removeArrowVisu(const std::string &layerName, const std::string &arrowName, const ::Ice::Current& = ::Ice::Current());
     virtual void removeArrowDebugLayerVisu(const std::string& arrowName, const ::Ice::Current& = ::Ice::Current());
 
+    /*!
+     * \brief setRobotVisu Initializes a robot visualization
+     * \param layerName The layer
+     * \param robotName The identifier of the robot
+     * \param robotFile The filename of the robot. The robot must be locally present in a project.
+     * \param armarxProject Additional armarx project that should be used to search the robot. Must be locally available and accessible through the armarx cmake search procedure.
+     */
+    virtual void setRobotVisu(const std::string &layerName, const std::string &robotName, const std::string &robotFile, const std::string &armarxProject, const ::Ice::Current& = ::Ice::Current());
+    virtual void updateRobotPose(const std::string &layerName, const std::string &robotName, const ::armarx::PoseBasePtr &globalPose, const ::Ice::Current& = ::Ice::Current());
+    virtual void updateRobotConfig(const std::string &layerName, const std::string &robotName, const std::map< std::string, float> &configuration, const ::Ice::Current& = ::Ice::Current());
+    /*!
+     * \brief updateRobotColor Colorizes the robot visualization
+     * \param layerName The layer
+     * \param robotName The robot identifyer
+     * \param c The draw color, if all is set to 0, the colorization is disabled (i.e. the original vizaulization shows up)
+     */
+    virtual void updateRobotColor(const std::string &layerName, const std::string &robotName, const armarx::DrawColor &c, const ::Ice::Current& = ::Ice::Current());
+    virtual void removeRobotVisu(const std::string &layerName, const std::string &robotName, const ::Ice::Current& = ::Ice::Current());
+
     virtual void clearLayer(const std::string& layerName, const ::Ice::Current& = ::Ice::Current());
     virtual void clearDebugLayer(const ::Ice::Current& = ::Ice::Current());
 
@@ -222,10 +241,11 @@ protected:
 
     struct DrawData
     {
-        DrawData(){active=false;}
+        DrawData(){active=false;update=false;}
         std::string layerName;
         std::string name;
         bool active;
+        bool update;
     };
 
     struct CoordData : public DrawData
@@ -280,6 +300,21 @@ protected:
         float width;
         VirtualRobot::VisualizationFactory::Color color;
     };
+    struct RobotData : public DrawData
+    {
+        RobotData(){updateColor = false; updatePose = false; updateConfig = false;}
+        std::string robotFile;
+        std::string armarxProject;
+        
+        bool updateColor;
+        VirtualRobot::VisualizationFactory::Color color;
+
+        bool updatePose;
+        Eigen::Matrix4f globalPose;
+
+        bool updateConfig;
+        std::map < std::string, float > configuration;
+    };
 
     struct UpdateData
     {
@@ -291,6 +326,7 @@ protected:
         std::map<std::string, PointCloudData> pointcloud;
         std::map<std::string, PolygonData> polygons;
         std::map<std::string, ArrowData> arrows;
+        std::map<std::string, RobotData> robots;
     };
 
     UpdateData accumulatedUpdateData;
@@ -306,6 +342,7 @@ protected:
     void drawPointCloud(const PointCloudData &d);
     void drawPolygon(const PolygonData &d);
     void drawArrow(const ArrowData &d);
+    void drawRobot(const RobotData &d);
 
     void removeCoordSystem(const std::string& layerName, const std::string &name);
     void removeLine(const std::string& layerName, const std::string &name);
@@ -315,6 +352,7 @@ protected:
     void removePointCloud(const std::string& layerName, const std::string &name);
     void removePolygon(const std::string& layerName, const std::string &name);
     void removeArrow(const std::string& layerName, const std::string &name);
+    void removeRobot(const std::string& layerName, const std::string &name);
 
     void setLayerVisibility(const std::string& layerName, bool visible);
 
@@ -332,6 +370,7 @@ protected:
         std::map<std::string, SoSeparator*> addedPointCloudVisualizations;
         std::map<std::string, SoSeparator*> addedPolygonVisualizations;
         std::map<std::string, SoSeparator*> addedArrowVisualizations;
+        std::map<std::string, SoSeparator*> addedRobotVisualizations;
 
         bool visible;
     };
@@ -342,7 +381,9 @@ protected:
      * \return The requested layer.
      */
     Layer &requestLayer(const std::string& layerName);
+    VirtualRobot::RobotPtr requestRobot(const RobotData &d);
 
+    std::map < std::string, VirtualRobot::RobotPtr > activeRobots;
     SoSeparator* coinVisu;
 
     bool verbose;
diff --git a/source/RobotAPI/interface/visualization/DebugDrawerInterface.ice b/source/RobotAPI/interface/visualization/DebugDrawerInterface.ice
index bc0454a50..ea6a03bc5 100644
--- a/source/RobotAPI/interface/visualization/DebugDrawerInterface.ice
+++ b/source/RobotAPI/interface/visualization/DebugDrawerInterface.ice
@@ -27,6 +27,7 @@
 #include <Core/interface/core/UserException.ice>
 #include <Core/interface/core/BasicTypes.ice>
 #include <RobotAPI/interface/core/PoseBase.ice>
+#include <RobotAPI/interface/units/KinematicUnitInterface.ice>
 
 module armarx
 {
@@ -89,6 +90,25 @@ module armarx
         void setPointCloudVisu(string layerName, string pointCloudName, DebugDrawerPointCloud pointCloud);
         void setPolygonVisu(string layerName, string polygonName, PolygonPointList polygonPoints, DrawColor colorInner, DrawColor colorBorder, float lineWidth);
         void setArrowVisu(string layerName, string arrowName, Vector3Base position, Vector3Base direction, DrawColor color, float length, float width);
+        
+        /*!
+         * \brief setRobotVisu Initializes a robot visualization
+         * \param layerName The layer
+         * \param robotName The identifier of the robot
+         * \param robotFile The filename of the robot. The robot must be locally present in a project.
+         * \param armarxProject Additional armarx project that should be used to search the robot. Must be locally available and accessible through the armarx cmake search procedure.
+         */
+        void setRobotVisu(string layerName, string robotName, string robotFile, string armarxProject);
+        void updateRobotPose(string layerName, string robotName, PoseBase globalPose);
+        void updateRobotConfig(string layerName, string robotName, NameValueMap configuration);
+        /*!
+         * \brief updateRobotColor Colorizes the robot visualization
+         * \param layerName The layer
+         * \param robotName The robot identifyer
+         * \param c The draw color, if all is set to 0, the colorization is disabled (i.e. the original vizaulization shows up)
+         */
+        void updateRobotColor(string layerName, string robotName, DrawColor c);
+        void removeRobotVisu(string layerName, string robotName);
 
         /*!
          * \brief setPoseVisu draws on the "debug" layer
-- 
GitLab