diff --git a/source/RobotAPI/applications/CMakeLists.txt b/source/RobotAPI/applications/CMakeLists.txt
index 8af364a4a4213d9210698826a3540b553343260d..9c60131a806481066122ca5a6a9fbf99d57f6681 100644
--- a/source/RobotAPI/applications/CMakeLists.txt
+++ b/source/RobotAPI/applications/CMakeLists.txt
@@ -53,3 +53,4 @@ add_subdirectory(StatechartExecutorExample)
 
 
 add_subdirectory(NaturalIKTest)
+add_subdirectory(DynamicObstacleManager)
diff --git a/source/RobotAPI/applications/DynamicObstacleManager/CMakeLists.txt b/source/RobotAPI/applications/DynamicObstacleManager/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e8cd2eda8e4ab5fab7909b9b1a2febf0ccbe4bf4
--- /dev/null
+++ b/source/RobotAPI/applications/DynamicObstacleManager/CMakeLists.txt
@@ -0,0 +1,7 @@
+armarx_component_set_name("DynamicObstacleManager")
+
+set(COMPONENT_LIBS
+    DynamicObstacleManager
+)
+
+armarx_add_component_executable("main.cpp")
diff --git a/source/RobotAPI/applications/DynamicObstacleManager/main.cpp b/source/RobotAPI/applications/DynamicObstacleManager/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2b115f14589702625322d2b461a5adf38aa98643
--- /dev/null
+++ b/source/RobotAPI/applications/DynamicObstacleManager/main.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian Peller-Konrad <fabian.peller-konrad@kit.edu>
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+// STD/STL
+#include <string>
+
+// ArmarX
+#include <ArmarXCore/core/application/Application.h>
+#include <ArmarXCore/core/Component.h>
+
+// Component
+#include <RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h>
+
+using namespace armarx;
+
+int main(int argc, char* argv[])
+{
+    const std::string name = DynamicObstacleManager::default_name;
+    return runSimpleComponentApp<DynamicObstacleManager>(argc, argv, name);
+}
diff --git a/source/RobotAPI/components/CMakeLists.txt b/source/RobotAPI/components/CMakeLists.txt
index e3adea9f26ea18835bac052d9badc959d2bbd8d3..8841868b70021ca022dc06c8d5940a9ffd10e123 100644
--- a/source/RobotAPI/components/CMakeLists.txt
+++ b/source/RobotAPI/components/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(DebugDrawer)
 add_subdirectory(DebugDrawerToArViz)
 add_subdirectory(DSObstacleAvoidance)
 add_subdirectory(DummyTextToSpeech)
+add_subdirectory(DynamicObstacleManager)
 add_subdirectory(EarlyVisionGraph)
 add_subdirectory(FrameTracking)
 add_subdirectory(GamepadControlUnit)
diff --git a/source/RobotAPI/components/DSObstacleAvoidance/CMakeLists.txt b/source/RobotAPI/components/DSObstacleAvoidance/CMakeLists.txt
index ff53d0508dd334b6095daa28a7e7b00438fa3ff8..4eb4b16a3d8df576ee0a2a870aaced1f69a78816 100644
--- a/source/RobotAPI/components/DSObstacleAvoidance/CMakeLists.txt
+++ b/source/RobotAPI/components/DSObstacleAvoidance/CMakeLists.txt
@@ -9,6 +9,12 @@ if(Eigen3_FOUND)
     include_directories(${Eigen3_INCLUDE_DIR})
 endif()
 
+find_package(Simox QUIET)
+armarx_build_if(Simox_FOUND "Simox not available")
+if(Simox_FOUND)
+    include_directories(${Simox_INCLUDE_DIR})
+endif()
+
 find_package(PythonLibs 3.6 QUIET)
 armarx_build_if(PYTHONLIBS_FOUND "Python libs not available")
 if(PYTHONLIBS_FOUND)
diff --git a/source/RobotAPI/components/DynamicObstacleManager/CMakeLists.txt b/source/RobotAPI/components/DynamicObstacleManager/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d32b8830630d33ae0a1666477e77e62297506c0a
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/CMakeLists.txt
@@ -0,0 +1,53 @@
+armarx_component_set_name("DynamicObstacleManager")
+
+
+find_package(Eigen3 QUIET)
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+if(Eigen3_FOUND)
+    include_directories(${Eigen3_INCLUDE_DIR})
+endif()
+
+find_package(Simox ${ArmarX_Simox_VERSION} QUIET)
+armarx_build_if(Simox_FOUND "Simox ${ArmarX_Simox_VERSION} or later not available")
+if (Simox_FOUND)
+    include_directories(${Simox_INCLUDE_DIRS})
+endif()
+
+find_package(OpenCV QUIET)
+armarx_build_if(OpenCV_FOUND "OpenCV not available")
+if(OpenCV_FOUND)
+    include_directories(${OpenCV_INCLUDE_DIRS})
+endif()
+
+set(COMPONENT_LIBS
+    ArmarXCore
+    ArmarXCoreInterfaces
+    RobotAPICore
+    RobotAPIComponentPlugins
+    RobotAPIInterfaces
+    ${OpenCV_LIBS}
+    ${Simox_LIBS}
+)
+
+set(SOURCES
+    ./DynamicObstacleManager.cpp
+    ./ManagedObstacle.cpp
+)
+set(HEADERS
+    ./DynamicObstacleManager.h
+    ./ManagedObstacle.h
+)
+
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+
+#find_package(MyLib QUIET)
+#armarx_build_if(MyLib_FOUND "MyLib not available")
+# all target_include_directories must be guarded by if(Xyz_FOUND)
+# for multiple libraries write: if(X_FOUND AND Y_FOUND)....
+#if(MyLib_FOUND)
+#    target_include_directories(DynamicObstacleManager PUBLIC ${MyLib_INCLUDE_DIRS})
+#endif()
+
+# add unit tests
+# add_subdirectory(test)
diff --git a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e39c54aecc85964c9c5f5b4ec0fe5d6ea37a20c3
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp
@@ -0,0 +1,430 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian PK ( fabian dot peller-konrad at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "DynamicObstacleManager.h"
+
+// STD/STL
+#include <string>
+#include <vector>
+#include <cmath>
+#include <limits>
+
+// Ice
+#include <Ice/Current.h>
+using namespace Ice;
+
+// Eigen
+#include <Eigen/Core>
+using namespace Eigen;
+
+// Simox
+#include <VirtualRobot/Nodes/RobotNode.h>
+#include <VirtualRobot/XML/RobotIO.h>
+
+// ArmarX
+#include <ArmarXCore/util/time.h>
+#include <ArmarXCore/core/Component.h>
+#include <RobotAPI/interface/core/PoseBase.h>
+#include <RobotAPI/libraries/core/Pose.h>
+
+
+using namespace armarx;
+
+
+const std::string
+armarx::DynamicObstacleManager::default_name = "DynamicObstacleManager";
+
+namespace armarx
+{
+
+    DynamicObstacleManager::DynamicObstacleManager() noexcept :
+        m_obstacle_index(0),
+        m_decay_after_ms(5000),
+        m_periodic_task_interval(500),
+        m_min_value_for_accepting(1000),
+        m_min_coverage_of_obstacles(0.7f),
+        m_min_coverage_of_line_samples_in_obstacle(0.9f),
+        m_min_size_of_obstacles(100),
+        m_min_length_of_lines(50),
+        m_max_size_of_obstacles(600),
+        m_max_length_of_lines(10000),
+        m_thickness_of_lines(200),
+        m_security_margin_for_obstacles(500),
+        m_security_margin_for_lines(400),
+        m_remove_enabled(false),
+        m_only_visualize(false),
+        m_allow_spwan_inside(false)
+    {
+
+    }
+
+
+    std::string DynamicObstacleManager::getDefaultName() const
+    {
+        return DynamicObstacleManager::default_name;
+    }
+
+
+    void DynamicObstacleManager::onInitComponent()
+    {
+
+    }
+
+
+    void DynamicObstacleManager::onConnectComponent()
+    {
+        m_decay_factor = m_periodic_task_interval;
+        m_access_bonus = m_periodic_task_interval;
+
+        m_update_obstacles = new PeriodicTask<DynamicObstacleManager>(this,
+                &DynamicObstacleManager::update_decayable_obstacles, m_periodic_task_interval);
+        m_update_obstacles->start();
+    }
+
+    void DynamicObstacleManager::onDisconnectComponent()
+    {
+        m_update_obstacles->stop();
+    }
+
+    void DynamicObstacleManager::onExitComponent()
+    {
+
+    }
+
+    void DynamicObstacleManager::add_decayable_obstacle(const Eigen::Vector2f& e_origin, float e_rx, float e_ry, float e_yaw, const Ice::Current&)
+    {
+        // TODO
+    }
+
+
+    void DynamicObstacleManager::add_decayable_line_segment(const Eigen::Vector2f& line_start, const Eigen::Vector2f& line_end, const Ice::Current&)
+    {
+        const Eigen::Vector2f difference_vec = line_end - line_start;
+        const float length = difference_vec.norm();
+        const Eigen::Vector2f center_vec = line_start + 0.5 * difference_vec;
+        const Eigen::Vector2f difference_vec_normed = difference_vec.normalized();
+        const float dot_product = difference_vec_normed(0);
+        const float cross_product = difference_vec_normed(1);
+        float yaw = acos(dot_product);
+
+        if (cross_product < 0)
+        {
+            yaw = 2 * M_PI - yaw;
+        }
+
+        if (length < m_min_length_of_lines)
+        {
+            return;
+        }
+
+
+        {
+            std::shared_lock<std::shared_mutex> l(m_managed_obstacles_mutex);
+
+            // First check own obstacles
+            for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles)
+            {
+                std::lock_guard<std::shared_mutex> l(managed_obstacle->m_mutex);
+                float coverage = ManagedObstacle::line_segment_ellipsis_coverage(
+                {managed_obstacle->m_obstacle.posX, managed_obstacle->m_obstacle.posY}, managed_obstacle->m_obstacle.axisLengthX, managed_obstacle->m_obstacle.axisLengthY, managed_obstacle->m_obstacle.yaw,
+                line_start, line_end);
+                //ARMARX_DEBUG << "The coverage of the new line to obstacle " << managed_obstacle.obstacle.name << "(" << ManagedObstacle::calculateObstacleArea(managed_obstacle.obstacle) << ") is " << coverage;
+                if (coverage >= m_min_coverage_of_line_samples_in_obstacle)
+                {
+                    // Obstacle already in list. Increase counter and update current obstacle.
+                    managed_obstacle->line_matches.push_back(line_start);
+                    managed_obstacle->line_matches.push_back(line_end);
+                    managed_obstacle->m_last_matched = IceUtil::Time::now();
+                    return;
+                }
+            }
+        }
+
+        // Second check the obstacles from the obstacle avoidance
+        for (const auto& published_obstacle : m_obstacle_detection->getObstacles())
+        {
+            float coverage = ManagedObstacle::line_segment_ellipsis_coverage(
+            {published_obstacle.posX, published_obstacle.posY}, published_obstacle.axisLengthX, published_obstacle.axisLengthY, published_obstacle.yaw,
+            line_start, line_end);
+            if (coverage >= m_min_coverage_of_line_samples_in_obstacle)
+            {
+                // If own managed obstacle we already updatet its value. If its a static obstacle from the obstacle avoidance, then we can't update the position anyway...
+                ARMARX_DEBUG << "Found the obstacle in the static obstacle list! Matching name: " << published_obstacle.name;
+                return;
+            }
+        }
+
+        ARMARX_DEBUG << " No matching obstacle found. Create new obstacle and add to list";
+        ManagedObstaclePtr new_managed_obstacle(new ManagedObstacle());
+        new_managed_obstacle->m_obstacle.name = "managed_obstacle_" + std::to_string(m_obstacle_index++);
+        new_managed_obstacle->m_obstacle.posX = center_vec(0);
+        new_managed_obstacle->m_obstacle.posY = center_vec(1);
+        new_managed_obstacle->m_obstacle.refPosX = center_vec(0);
+        new_managed_obstacle->m_obstacle.refPosY = center_vec(1);
+        new_managed_obstacle->m_obstacle.yaw = yaw;
+        new_managed_obstacle->m_obstacle.axisLengthX = std::clamp(length * 0.5f, static_cast<float>(m_min_length_of_lines), static_cast<float>(m_max_length_of_lines));
+        new_managed_obstacle->m_obstacle.axisLengthY = m_thickness_of_lines;
+        new_managed_obstacle->m_obstacle.safetyMarginX = m_security_margin_for_lines;
+        new_managed_obstacle->m_obstacle.safetyMarginY = m_security_margin_for_lines;
+        new_managed_obstacle->m_last_matched = IceUtil::Time::now();
+        new_managed_obstacle->m_published = false;
+        new_managed_obstacle->m_value = m_min_value_for_accepting * 0.5;
+        new_managed_obstacle->position_buffer_index = 0;
+        new_managed_obstacle->position_buffer_fillctr = 0;
+        new_managed_obstacle->line_matches.push_back(line_start);
+        new_managed_obstacle->line_matches.push_back(line_end);
+
+        {
+            std::lock_guard<std::shared_mutex> l(m_managed_obstacles_mutex);
+            m_managed_obstacles.push_back(new_managed_obstacle);
+        }
+    }
+
+
+    void DynamicObstacleManager::remove_all_decayable_obstacles(const Ice::Current&)
+    {
+        std::lock_guard l(m_managed_obstacles_mutex);
+
+        ARMARX_DEBUG << "Remove all obstacles from obstacle map by setting their value to -inf";
+        for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles)
+        {
+            managed_obstacle->m_value = std::numeric_limits<double>::min();
+            managed_obstacle->m_updated = true;
+        }
+    }
+
+    void DynamicObstacleManager::remove_obstacle(const std::string& name, const Ice::Current&)
+    {
+        std::lock_guard l(m_managed_obstacles_mutex);
+
+        ARMARX_DEBUG << "Remove Obstacle " << name << " from obstacle map and from obstacledetection";
+        for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles)
+        {
+            if(managed_obstacle->m_obstacle.name == name)
+            {
+                managed_obstacle->m_value = std::numeric_limits<double>::min();
+                managed_obstacle->m_updated = true;
+                managed_obstacle->m_published = false;
+                m_obstacle_detection->removeObstacle(name);
+                m_obstacle_detection->updateEnvironment();
+                return; // We assume unique names
+            }
+        }
+    }
+
+    void DynamicObstacleManager::directly_update_obstacle(const std::string& name, const Eigen::Vector2f& obs_pos, float e_rx, float e_ry, float e_yaw, const Ice::Current&)
+    {
+        obstacledetection::Obstacle new_unmanaged_obstacle;
+        new_unmanaged_obstacle.name = name;
+        new_unmanaged_obstacle.posX = obs_pos(0);
+        new_unmanaged_obstacle.posY = obs_pos(1);
+        new_unmanaged_obstacle.refPosX = obs_pos(0);
+        new_unmanaged_obstacle.refPosY = obs_pos(1);
+        new_unmanaged_obstacle.yaw = e_yaw;
+        new_unmanaged_obstacle.axisLengthX = std::clamp(e_rx, static_cast<float>(m_min_size_of_obstacles), static_cast<float>(m_max_size_of_obstacles));
+        new_unmanaged_obstacle.axisLengthY = std::clamp(e_ry, static_cast<float>(m_min_size_of_obstacles), static_cast<float>(m_max_size_of_obstacles));
+        new_unmanaged_obstacle.safetyMarginX = m_security_margin_for_obstacles;
+        new_unmanaged_obstacle.safetyMarginY = m_security_margin_for_obstacles;
+        m_obstacle_detection->updateObstacle(new_unmanaged_obstacle);
+        m_obstacle_detection->updateEnvironment();
+    }
+
+
+    void DynamicObstacleManager::update_decayable_obstacles()
+    {
+        IceUtil::Time started = IceUtil::Time::now();
+        std::vector<std::string> remove_obstacles;
+
+        // Some debug definitions
+        viz::Layer obstacleLayer = arviz.layer(m_obstacle_manager_layer_name);
+
+        // Update positions
+        {
+            std::shared_lock<std::shared_mutex> l(m_managed_obstacles_mutex);
+            if (!m_managed_obstacles.size())
+            {
+                return;
+            }
+
+            for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles)
+            {
+                std::lock_guard<std::shared_mutex> l(managed_obstacle->m_mutex);
+                managed_obstacle->update_position(m_thickness_of_lines);
+            }
+        }
+
+
+        // Update obstacle avoidance
+        int checked_obstacles = 0;
+        bool updated = false;
+        int published_obstacles = 0;
+        int updated_obstacles = 0;
+        {
+            std::lock_guard l(m_managed_obstacles_mutex);
+            std::sort(m_managed_obstacles.begin(), m_managed_obstacles.end(), ManagedObstacle::ComparatorDESCPrt);
+
+            checked_obstacles = m_managed_obstacles.size();
+
+            for (ManagedObstaclePtr& managed_obstacle : m_managed_obstacles)
+            {
+                std::lock_guard<std::shared_mutex> l(managed_obstacle->m_mutex);
+                if (!managed_obstacle->m_updated)
+                {
+                    managed_obstacle->m_value = std::max(-1.0f, managed_obstacle->m_value - m_decay_factor);
+                }
+                else
+                {
+                    managed_obstacle->m_value = std::min(1.0f * m_decay_after_ms, managed_obstacle->m_value + m_access_bonus);
+                }
+
+                if (managed_obstacle->m_published)
+                {
+                    if (managed_obstacle->m_value < m_min_value_for_accepting)
+                    {
+                        updated_obstacles++;
+                        managed_obstacle->m_published = false;
+                        if (!m_only_visualize)
+                        {
+                            m_obstacle_detection->removeObstacle(managed_obstacle->m_obstacle.name);
+                            updated = true;
+                        }
+                    }
+                    else
+                    {
+                        published_obstacles++;
+                        if (managed_obstacle->m_updated)
+                        {
+                            updated_obstacles++;
+                            if (!m_only_visualize)
+                            {
+                                m_obstacle_detection->updateObstacle(managed_obstacle->m_obstacle);
+                                updated = true;
+                            }
+                            //visualize_obstacle(obstacleLayer, managed_obstacle, armarx::DrawColor{0, 1, 1, std::min(0.9f, managed_obstacle->m_value / m_decay_after_ms)}, 50, false);
+                        }
+                        else
+                        {
+                            //visualize_obstacle(obstacleLayer, managed_obstacle, armarx::DrawColor{0, 1, 0, std::min(0.9f, managed_obstacle->m_value / m_decay_after_ms)}, 50, false);
+                        }
+                    }
+                }
+                else // if (!managed_obstacle.published)
+                {
+                    if (managed_obstacle->m_value >= m_min_value_for_accepting)
+                    {
+                        published_obstacles++;
+                        updated_obstacles++;
+                        managed_obstacle->m_published = true;
+                        if (!m_only_visualize)
+                        {
+                            m_obstacle_detection->updateObstacle(managed_obstacle->m_obstacle);
+                            updated = true;
+                        }
+                        //visualize_obstacle(obstacleLayer, managed_obstacle, armarx::DrawColor{0, 1, 0, std::min(0.9f, managed_obstacle->m_value / m_decay_after_ms)}, 50, false);
+                    }
+                    else if (managed_obstacle->m_value < 0 && m_remove_enabled) // Completely forget the obstacle
+                    {
+                        remove_obstacles.push_back(managed_obstacle->m_obstacle.name);
+                    }
+                    else if (managed_obstacle->m_updated)
+                    {
+                        visualize_obstacle(obstacleLayer, managed_obstacle, armarx::DrawColor{1, 1, 1, std::min(0.9f, managed_obstacle->m_value / m_min_value_for_accepting)}, 40, true);
+                    }
+                    else
+                    {
+                        visualize_obstacle(obstacleLayer, managed_obstacle, armarx::DrawColor{1, 1, 1, std::min(0.9f, managed_obstacle->m_value / m_min_value_for_accepting)}, 40, true);
+                    }
+                }
+                managed_obstacle->m_updated = false;
+            }
+        }
+
+        if (updated)
+        {
+            m_obstacle_detection->updateEnvironment();
+        }
+        arviz.commit({obstacleLayer});
+
+        if (!remove_obstacles.empty())
+        {
+            std::lock_guard<std::shared_mutex> l(m_managed_obstacles_mutex);
+            for (const auto& name : remove_obstacles)
+            {
+                // TODO schöner machen ohne loop. Iteratoren in main loop
+                m_managed_obstacles.erase(
+                    std::remove_if(
+                        m_managed_obstacles.begin(),
+                        m_managed_obstacles.end(),
+                        [&](const ManagedObstaclePtr & oc)
+                {
+                    return oc->m_obstacle.name == name;
+                }
+                    ),
+                m_managed_obstacles.end()
+                );
+            }
+        }
+
+        ARMARX_DEBUG << "Finished updating the " << checked_obstacles << " managed obstacles (removed: " << remove_obstacles.size() << ", updated: " << updated_obstacles << "). " << published_obstacles << " of them should be published. The whole operation took " << (IceUtil::Time::now() - started).toMilliSeconds() << "ms";
+    }
+
+    void DynamicObstacleManager::visualize_obstacle(viz::Layer& layer, const ManagedObstaclePtr& o, const armarx::DrawColor& color, double pos_z, bool text)
+    {
+        // Visualize ellipses.m_obstacle_manager_layer_name
+        Eigen::Vector3f dim(o->m_obstacle.axisLengthX * 2,
+                            o->m_obstacle.axisLengthY * 2,
+                            o->m_obstacle.axisLengthZ * 2);
+
+        const std::string name = o->m_obstacle.name;
+
+        layer.add(viz::Box(name).position(Eigen::Vector3f(o->m_obstacle.posX, o->m_obstacle.posY, pos_z))
+                  .orientation(Eigen::AngleAxisf(o->m_obstacle.yaw, Eigen::Vector3f::UnitZ()).toRotationMatrix())
+                  .size(dim).color(color.r, color.g, color.b, color.a));
+
+    }
+
+
+    armarx::PropertyDefinitionsPtr DynamicObstacleManager::createPropertyDefinitions()
+    {
+        PropertyDefinitionsPtr defs{new ComponentPropertyDefinitions{getConfigIdentifier()}};
+
+        defs->component(m_obstacle_detection, "PlatformObstacleAvoidance", "ObstacleAvoidanceName", "The name of the used obstacle avoidance interface");
+
+        defs->optional(m_min_coverage_of_obstacles, "MinSampleRatioPerEllipsis", "Minimum percentage of samples which have to be in an elllipsis to be considered as known obsacle");
+        defs->optional(m_min_coverage_of_line_samples_in_obstacle, "MinSampleRatioPerLineSegment", "Minimum percentage of samples which have to be in an elllipsis to be considered as known obsacle");
+        defs->optional(m_min_size_of_obstacles, "MinObstacleSize", "The minimal obstacle size in mm.");
+        defs->optional(m_max_size_of_obstacles, "MaxObstacleSize", "The maximal obstacle size in mm.");
+        defs->optional(m_min_length_of_lines, "MinLengthOfLines", "Minimum length of lines in mm");
+        defs->optional(m_max_length_of_lines, "MaxLengthOfLines", "Maximum length of lines in mm");
+        defs->optional(m_decay_after_ms, "MaxObstacleValue", "Maximum value for the obstacles");
+        defs->optional(m_min_value_for_accepting, "MinObstacleValueForAccepting", "Minimum value for the obstacles to get accepted");
+        defs->optional(m_periodic_task_interval, "UpdateInterval", "The interval to check the obstacles");
+        defs->optional(m_thickness_of_lines, "LineThickness", "The thickness of line obstacles");
+        defs->optional(m_security_margin_for_obstacles, "ObstacleSecurityMargin", "Security margin of ellipsis obstacles");
+        defs->optional(m_security_margin_for_lines, "LineSecurityMargin", "Security margin of line obstacles");
+        defs->optional(m_remove_enabled, "EnableRemove", "Delete Obstacles when value < 0");
+        defs->optional(m_only_visualize, "OnlyVisualizeObstacles", "Connection to obstacle avoidance");
+        defs->optional(m_allow_spwan_inside, "AllowInRobotSpawning", "Allow obstacles to spawn inside the robot");
+
+        return defs;
+    }
+}
diff --git a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..371ccbc3e9099e5baed3ae8165cea453ba2059f9
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.h
@@ -0,0 +1,123 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian PK ( fabian dot peller-konrad at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+
+// STD/STL
+#include <array>
+#include <string>
+#include <tuple>
+#include <vector>
+#include <shared_mutex>
+
+// Eigen
+#include <SimoxUtility/EigenStdVector.h>
+#include <Eigen/Geometry>
+
+// Ice
+#include <Ice/Current.h>
+
+// ArmarX
+#include <ArmarXCore/interface/observers/ObserverInterface.h>
+#include <ArmarXCore/core/services/tasks/PeriodicTask.h>
+#include <ArmarXCore/util/CPPUtility/TripleBuffer.h>
+
+// Managed Objects
+#include <RobotAPI/components/DynamicObstacleManager/ManagedObstacle.h>
+
+// ObstacleAvoidance
+#include <RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.h>
+#include <RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.h>
+
+// ArViz
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
+
+namespace armarx
+{
+
+    class DynamicObstacleManager :
+        virtual public Component,
+        virtual public DynamicObstacleManagerInterface,
+        virtual public ArVizComponentPluginUser
+    {
+    public:
+
+        DynamicObstacleManager() noexcept;
+
+        std::string getDefaultName() const override;
+
+        void add_decayable_obstacle(const Eigen::Vector2f&, float, float, float, const Ice::Current& = Ice::Current()) override;
+        void add_decayable_line_segment(const Eigen::Vector2f&, const Eigen::Vector2f&, const Ice::Current& = Ice::Current()) override;
+        void remove_all_decayable_obstacles(const Ice::Current& = Ice::Current()) override;
+        void directly_update_obstacle(const std::string& name, const Eigen::Vector2f&, float, float, float, const Ice::Current& = Ice::Current()) override;
+        void remove_obstacle(const std::string& name, const Ice::Current& = Ice::Current()) override;
+
+    protected:
+        void onInitComponent() override;
+        void onConnectComponent() override;
+        void onDisconnectComponent() override;
+        void onExitComponent() override;
+        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
+
+    private:
+        void update_decayable_obstacles();
+
+        void visualize_obstacle(viz::Layer& l, const ManagedObstaclePtr& o, const armarx::DrawColor& color, double z_pos, bool);
+
+    public:
+        static const std::string default_name;
+
+    private:
+        const std::string m_obstacle_manager_layer_name = "DynamicObstacleManagerObstacles";
+
+        unsigned long m_obstacle_index;
+
+        std::vector<ManagedObstaclePtr> m_managed_obstacles;
+        std::shared_mutex m_managed_obstacles_mutex;
+
+        PeriodicTask<DynamicObstacleManager>::pointer_type m_update_obstacles;
+        unsigned int m_decay_after_ms;
+        unsigned int m_periodic_task_interval;
+        unsigned int m_decay_factor;
+        unsigned int m_access_bonus;
+        unsigned int m_min_value_for_accepting;
+
+        float m_min_coverage_of_obstacles;
+        float m_min_coverage_of_line_samples_in_obstacle;
+        unsigned int m_min_size_of_obstacles;
+        unsigned int m_min_length_of_lines;
+        unsigned int m_max_size_of_obstacles;
+        unsigned int m_max_length_of_lines;
+        unsigned int m_thickness_of_lines;
+        unsigned int m_security_margin_for_obstacles;
+        unsigned int m_security_margin_for_lines;
+
+        bool m_remove_enabled;
+        bool m_only_visualize;
+        bool m_allow_spwan_inside;
+
+        ObstacleDetectionInterface::ProxyType m_obstacle_detection;
+
+    };
+}
diff --git a/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4d33d61f70cf01d5a54889c2f5c487719cb3fafc
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.cpp
@@ -0,0 +1,313 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian PK ( fabian dot peller-konrad at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "ManagedObstacle.h"
+
+// STD/STL
+#include <string>
+#include <vector>
+
+// Ice
+#include <Ice/Current.h>
+using namespace Ice;
+
+// OpenCV
+#include <opencv2/core.hpp>
+
+// Eigen
+#include <Eigen/Core>
+
+// ArmarX
+#include <RobotAPI/interface/core/PoseBase.h>
+#include <RobotAPI/libraries/core/Pose.h>
+
+using namespace Eigen;
+using namespace armarx;
+
+namespace armarx
+{
+
+    double ManagedObstacle::calculateObstacleArea(const obstacledetection::Obstacle& o)
+    {
+        return M_PI * std::abs(o.axisLengthX) * std::abs(o.axisLengthY);
+    }
+
+    bool ManagedObstacle::point_ellipsis_coverage(const Eigen::Vector2f e_origin, const float e_rx, const float e_ry, const float e_yaw, const Eigen::Vector2f point)
+    {
+        // See https://stackoverflow.com/questions/7946187/point-and-ellipse-rotated-position-test-algorithm
+        const float sin = std::sin(e_yaw);
+        const float cos = std::cos(e_yaw);
+
+        const float a = cos * (point(0) - e_origin(0)) + sin * (point(1) - e_origin(1));
+        const float b = sin * (point(0) - e_origin(0)) - cos * (point(1) - e_origin(1));
+
+        const float e_rx_sq = e_rx * e_rx;
+        const float e_ry_sq = e_ry * e_ry;
+
+        return a * a * e_ry_sq + b * b * e_rx_sq <= e_rx_sq * e_ry_sq;
+    }
+
+    float ManagedObstacle::ellipsis_ellipsis_coverage(const Eigen::Vector2f e1_origin, const float e1_rx, const float e1_ry, const float e1_yaw, const Eigen::Vector2f e2_origin, const float e2_rx, const float e2_ry, const float e2_yaw)
+    {
+        // We use a very simple approach here: We sample points in one ellipsis and check whether it lies in the other (https://www.quora.com/Is-it-possible-to-generate-random-points-within-a-given-rotated-ellipse-without-using-rejection-sampling)
+        // For a real approach to intersect two ellipsis see https://arxiv.org/pdf/1106.3787.pdf
+
+        unsigned int SAMPLES = 100;
+        unsigned int matches = 0;
+        for (unsigned int i = 0; i < SAMPLES; ++i)
+        {
+            float theta = static_cast<float>(rand()) / static_cast<float>(RAND_MAX / 2 * M_PI);
+            float k = sqrt(static_cast<float>(rand()) / static_cast<float>(RAND_MAX));
+            Eigen::Vector2f sample(k * e2_rx * cos(theta), k * e2_ry * sin(theta));
+            //sample *= Eigen::Rotation2D(e2_yaw);
+            sample += e1_origin;
+
+            if (ManagedObstacle::point_ellipsis_coverage(e1_origin, e1_rx, e1_ry, e1_yaw, sample))
+            {
+                matches++;
+            }
+        }
+
+        return (1.0f * matches) / SAMPLES;
+    }
+
+    float ManagedObstacle::line_segment_ellipsis_coverage(const Eigen::Vector2f e_origin, const float e_rx, const float e_ry, const float e_yaw, const Eigen::Vector2f line_seg_start, const Eigen::Vector2f line_seg_end)
+    {
+        // Again we discretize the line into n points and we check the coverage of those points
+        const unsigned int SAMPLES = 40;
+        const Eigen::Vector2f difference_vec = line_seg_end - line_seg_start;
+        const Eigen::Vector2f difference_vec_normed = difference_vec.normalized();
+        const float distance = difference_vec.norm();
+        const float step_size = distance / SAMPLES;
+        const Eigen::Vector2f dir = difference_vec_normed * step_size;
+
+        unsigned int samples_in_ellipsis = 0;
+
+        // Sample over line segment with a fixed size
+        for (unsigned int i = 0; i < SAMPLES * 0.5; ++i)
+        {
+            Eigen::Vector2f start_sample = line_seg_start + i * dir;
+            Eigen::Vector2f end_sample = line_seg_end - i * dir;
+            unsigned int samples_in_ellipsis_this_iteration = 0;
+
+            for (const auto& point :
+                 {
+                     start_sample, end_sample
+                 })
+            {
+                if (ManagedObstacle::point_ellipsis_coverage(e_origin, e_rx, e_ry, e_yaw, point))
+                {
+                    ++samples_in_ellipsis;
+                    ++samples_in_ellipsis_this_iteration;
+                }
+            }
+
+            if (samples_in_ellipsis_this_iteration == 2)
+            {
+                // Last two points (from the outside) were inside this ellipsis, so the
+                // remaining ones are as well simce ellipsis are concave.  Consider this line
+                // segment as explained by the obstacle and bail early.
+                const unsigned int remaining_samples = SAMPLES - 2 * (i + 1);
+                return (1.0f * samples_in_ellipsis + remaining_samples) / SAMPLES;
+            }
+        }
+        return (1.0f * samples_in_ellipsis) / SAMPLES; // only if one point or no point in ellipsis
+    }
+
+    void ManagedObstacle::update_position(const unsigned int thickness)
+    {
+        if (line_matches.size() < 2)
+        {
+            return;
+        }
+
+        ARMARX_INFO << "Obstacle " << m_obstacle.name << " has " << line_matches.size() << " matching line segments since last update";
+
+        std::vector<float> x_pos;
+        std::vector<float> y_pos;
+        for (Eigen::Vector2f& match : line_matches)
+        {
+            ARMARX_INFO << "Match: " << match;
+            x_pos.push_back(match(0));
+            y_pos.push_back(match(1));
+        }
+
+        cv::Mat x(x_pos.size(), 1, CV_32F, x_pos.data());
+        cv::Mat y(y_pos.size(), 1, CV_32F, y_pos.data());
+
+        ARMARX_INFO << "X: " << x;
+        ARMARX_INFO << "Y: " << y;
+
+        cv::Mat data(x_pos.size(), 2, CV_32F);
+        x.col(0).copyTo(data.col(0));
+        y.col(0).copyTo(data.col(1));
+
+        ARMARX_INFO << "Data: " << data;
+
+        cv::PCA pca(data, cv::Mat(), CV_PCA_DATA_AS_ROW, 2);
+
+        cv::Mat mean = pca.mean;
+        ARMARX_INFO << "Mean: " << mean;
+        cv::Mat eigenvalues = pca.eigenvalues;
+        ARMARX_INFO << "Eigenvalues: " << eigenvalues;
+        cv::Mat eigenvectors = pca.eigenvectors;
+        ARMARX_INFO << "Eigenvectors: " << eigenvectors;
+
+        Eigen::Vector2f pca_center(mean.at<float>(0, 0), mean.at<float>(0, 1));
+        Eigen::Vector2f pca1_direction(eigenvectors.at<float>(0, 0), eigenvectors.at<float>(0, 1));
+        Eigen::Vector2f pca2_direction(eigenvectors.at<float>(1, 0), eigenvectors.at<float>(1, 1));
+        double pca1_eigenvalue = eigenvalues.at<float>(0, 0);
+        double pca2_eigenvalue = eigenvalues.at<float>(1, 0);
+
+        ARMARX_INFO << "PCA: Mean: " << pca_center;
+        ARMARX_INFO << "PCA1: Eigenvector: " << pca1_direction << ", Eigenvalue: " << pca1_eigenvalue;
+        ARMARX_INFO << "PCA2: Eigenvector: " << pca2_direction << ", Eigenvalue: " << pca2_eigenvalue;
+
+        // calculate yaw of best line (should be close to current yaw)
+        const Eigen::Vector2f difference_vec = pca1_direction;
+        const Eigen::Vector2f center_vec = pca_center;
+        //const Eigen::Vector2f difference_vec1_normed = difference_vec.normalized();
+
+        const float yaw1 = getXAxisAngle(difference_vec);
+        const float yaw2 = getXAxisAngle(-1 * difference_vec);
+
+        const float diff_origin_yaw1 = std::abs(yaw1 - m_obstacle.yaw);
+        const float diff_origin_yaw2 = std::abs(yaw2 - m_obstacle.yaw);
+        const float diff_origin_yaw1_opposite = std::abs(2 * M_PI - diff_origin_yaw1);
+        const float diff_origin_yaw2_opposite = std::abs(2 * M_PI - diff_origin_yaw2);
+
+
+        float yaw = yaw2;
+        if ((diff_origin_yaw1 < diff_origin_yaw2 && diff_origin_yaw1 < diff_origin_yaw2_opposite) || (diff_origin_yaw1_opposite < diff_origin_yaw2 && diff_origin_yaw1_opposite < diff_origin_yaw2_opposite))
+        {
+            yaw = yaw1;
+        }
+
+        // Print matches to debug drawer
+        //const std::string debug_line_name = "line_segment_input_" + std::to_string(m_input_index++);
+        //const armarx::Vector3BasePtr start_vec_3d{new Vector3(best_start(0), best_start(1), 50)};
+        //const armarx::Vector3BasePtr end_vec_3d{new Vector3(best_end(0), best_end(1), 50)};
+        //const armarx::Vector3BasePtr center_vec_3d{new Vector3(center_vec(0), center_vec(1), 50)};
+        //const armarx::Vector3BasePtr difference_vec_normed_3d{new Vector3(difference_vec1_normed(0), difference_vec1_normed(1), 0)};
+        //debug_drawer->setCylinderVisu(layer_name, debug_line_name, center_vec_3d, difference_vec_normed_3d, max_length, 15.f, armarx::DrawColor{1, 0, 0, 0.8});
+        //debug_drawer->setSphereVisu(layer_name, debug_line_name + "_ref", start_vec_3d, armarx::DrawColor{1, 1, 0, 0.8}, 35);
+        //debug_drawer->setSphereVisu(layer_name, debug_line_name + "_ref2", end_vec_3d, armarx::DrawColor{0, 1, 0, 0.8}, 35);
+
+        // Udate position buffer with new best line
+        position_buffer.at(position_buffer_index++) = std::make_tuple(center_vec(0), center_vec(1), yaw, sqrt(pca1_eigenvalue) * 1.3, std::max(1.0f * thickness, static_cast<float>(sqrt(pca2_eigenvalue)) * 1.3f)); // add 30% security margin to length of pca
+        position_buffer_index %= position_buffer.size();
+
+        position_buffer_fillctr++;
+        position_buffer_fillctr = std::min(position_buffer_fillctr, static_cast<unsigned int>(position_buffer.size()));
+
+        // Calculate means from position buffer
+        double sum_x_pos = 0;
+        double sum_y_pos = 0;
+        double sum_yaw = 0;
+        double sum_sin_yaw = 0;
+        double sum_cos_yaw = 0;
+        double sum_axisX = 0;
+        double sum_axisY = 0;
+
+        std::string yaws;
+        for (unsigned int i = 0; i < position_buffer_fillctr; ++i)
+        {
+            double current_x_pos = std::get<0>(position_buffer[i]);
+            double current_y_pos = std::get<1>(position_buffer[i]);
+            double current_yaw = std::get<2>(position_buffer[i]);
+            double current_axisX = std::get<3>(position_buffer[i]);
+            double current_axisY = std::get<4>(position_buffer[i]);
+            sum_x_pos += current_x_pos;
+            sum_y_pos += current_y_pos;
+            sum_yaw += current_yaw;
+            sum_sin_yaw += sin(current_yaw);
+            sum_cos_yaw += cos(current_yaw);
+            sum_axisX += current_axisX;
+            sum_axisY += current_axisY;
+
+            yaws += std::to_string(current_yaw) + ", ";
+        }
+
+        double mean_x_pos = sum_x_pos / position_buffer_fillctr;
+        double mean_y_pos = sum_y_pos / position_buffer_fillctr;
+        double mean_yaw =  atan2((1.0 / position_buffer_fillctr) * sum_sin_yaw, (1.0 / position_buffer_fillctr) * sum_cos_yaw); //sum_yaw  / position_buffer_fillctr; //std::fmod(sum_yaw, 2.0 * M_PI);
+        double mean_axisX = sum_axisX / position_buffer_fillctr;
+        double mean_axisY = sum_axisY / position_buffer_fillctr;
+        mean_yaw = normalizeYaw(mean_yaw);
+
+        // Update position and size of obstacle
+        m_obstacle.posX = mean_x_pos;
+        m_obstacle.posY = mean_y_pos;
+        m_obstacle.refPosX = mean_x_pos;
+        m_obstacle.refPosY = mean_y_pos;
+        m_obstacle.yaw = mean_yaw;
+        //if (mean_axisX > m_obstacle.axisLengthX)
+        //{
+        m_obstacle.axisLengthX = mean_axisX;
+        //}
+        //if (mean_axisY > m_obstacle.axisLengthY)
+        //{
+        m_obstacle.axisLengthY = mean_axisY;
+        //}
+
+        line_matches.clear();
+        m_updated = true;
+    }
+
+    float ManagedObstacle::normalizeYaw(float yaw) const
+    {
+        float pi2 = 2.0 * M_PI;
+        while (yaw < 0)
+        {
+            yaw += pi2;
+        }
+        while (yaw > pi2)
+        {
+            yaw -= pi2;
+        }
+        return yaw;
+    }
+
+    float ManagedObstacle::getAngleBetweenVectors(const Eigen::Vector2f& v1, const Eigen::Vector2f& v2) const
+    {
+        // Returns an angle between 0 and 180 degree (the minimum angle between the two vectors)
+        const Eigen::Vector2f v1_vec_normed = v1.normalized();
+        const Eigen::Vector2f v2_vec_normed = v2.normalized();
+        const float dot_product_vec = v1_vec_normed(0) * v2_vec_normed(0) + v1_vec_normed(1) * v2_vec_normed(1);
+        float yaw = acos(dot_product_vec);
+        return yaw;
+    }
+
+    float ManagedObstacle::getXAxisAngle(const Eigen::Vector2f& v) const
+    {
+        // Returns an angle between 0 and 360 degree (counterclockwise from x axis)
+        const Eigen::Vector2f v_vec_normed = v.normalized();
+        const float dot_product_vec = v_vec_normed(0);
+        const float cross_product_vec = v_vec_normed(1);
+        float yaw = acos(dot_product_vec);
+        if (cross_product_vec < 0)
+        {
+            yaw = 2 * M_PI - yaw;
+        }
+        return yaw;
+    }
+}
diff --git a/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.h b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.h
new file mode 100644
index 0000000000000000000000000000000000000000..95b7491d2d08e989321dcfdf30463acd46a95e9d
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/ManagedObstacle.h
@@ -0,0 +1,90 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian PK ( fabian dot peller-konrad at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+
+// STD/STL
+#include <array>
+#include <tuple>
+#include <shared_mutex>
+#include <string>
+#include <vector>
+
+// Eigen
+#include <Eigen/Geometry>
+
+// ArmarX
+#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
+#include <RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.h>
+
+
+namespace armarx
+{
+
+    class ManagedObstacle;
+    typedef std::shared_ptr<ManagedObstacle> ManagedObstaclePtr;
+
+    class ManagedObstacle
+    {
+    public:
+
+        static bool ComparatorDESCPrt(ManagedObstaclePtr& i, ManagedObstaclePtr& j)
+        {
+            return (ManagedObstacle::calculateObstacleArea(i->m_obstacle) > ManagedObstacle::calculateObstacleArea(j->m_obstacle));
+        }
+
+        void update_position(const unsigned int);
+
+        static double calculateObstacleArea(const obstacledetection::Obstacle& o);
+
+        static bool point_ellipsis_coverage(const Eigen::Vector2f e_origin, const float e_rx, const float e_ry, const float e_yaw, const Eigen::Vector2f point);
+
+        static float ellipsis_ellipsis_coverage(const Eigen::Vector2f e1_origin, const float e1_rx, const float e1_ry, const float e1_yaw, const Eigen::Vector2f e2_origin, const float e2_rx, const float e2_ry, const float e2_yaw);
+
+        static float line_segment_ellipsis_coverage(const Eigen::Vector2f e_origin, const float e_rx, const float e_ry, const float e_yaw, const Eigen::Vector2f line_seg_start, const Eigen::Vector2f line_seg_end);
+
+
+        obstacledetection::Obstacle m_obstacle;
+        IceUtil::Time m_last_matched;
+        bool m_published;
+        bool m_updated;
+        float m_value;
+        std::shared_mutex m_mutex;
+
+        unsigned int position_buffer_fillctr = 0;
+        unsigned int position_buffer_index = 0;
+        std::array<std::tuple<double, double, double, double, double>, 6> position_buffer; //x, y, yaw, axisX, axisY
+        std::vector<Eigen::Vector2f> line_matches; // points of line segments
+
+
+        unsigned long m_input_index = 0;
+    protected:
+
+    private:
+        float normalizeYaw(float yaw) const;
+        float getAngleBetweenVectors(const Eigen::Vector2f&, const Eigen::Vector2f&) const;
+        float getXAxisAngle(const Eigen::Vector2f&) const;
+
+    };
+}
diff --git a/source/RobotAPI/components/DynamicObstacleManager/test/CMakeLists.txt b/source/RobotAPI/components/DynamicObstacleManager/test/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7c1102988e196a553e2961ac2fda0a02cf286f15
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/test/CMakeLists.txt
@@ -0,0 +1,5 @@
+
+# Libs required for the tests
+SET(LIBS ${LIBS} ArmarXCore DynamicObstacleManager)
+ 
+armarx_add_test(DynamicObstacleManagerTest DynamicObstacleManagerTest.cpp "${LIBS}")
diff --git a/source/RobotAPI/components/DynamicObstacleManager/test/DynamicObstacleManagerTest.cpp b/source/RobotAPI/components/DynamicObstacleManager/test/DynamicObstacleManagerTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..52fa2345cd6c12f0cd6fd7cecb3a43564731605a
--- /dev/null
+++ b/source/RobotAPI/components/DynamicObstacleManager/test/DynamicObstacleManagerTest.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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    Armar6Skills::ArmarXObjects::DynamicObstacleManager
+ * @author     Fabian PK ( fabian dot peller-konrad at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE Armar6Skills::ArmarXObjects::DynamicObstacleManager
+
+#define ARMARX_BOOST_TEST
+
+#include <RobotAPI/Test.h>
+#include <Armar6Skills/components/DynamicObstacleManager/DynamicObstacleManager.h>
+
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(testExample)
+{
+    armarx::DynamicObstacleManager instance;
+
+    BOOST_CHECK_EQUAL(true, true);
+}
diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt
index 6ca8b8ee106668475988c67a2b26db34f895b640..c13ab4dcd519f7a19aec3f2af919b8a0a793604f 100644
--- a/source/RobotAPI/interface/CMakeLists.txt
+++ b/source/RobotAPI/interface/CMakeLists.txt
@@ -81,9 +81,7 @@ set(SLICE_FILES
 
     units/RobotUnit/TaskSpaceActiveImpedanceControl.ice
 
-    components/DSObstacleAvoidanceInterface.ice
-    components/FrameTrackingInterface.ice
-    components/ObstacleAvoidanceInterface.ice
+    components/FrameTrackingInterface.ice    
     components/RobotHealthInterface.ice
     components/RobotNameServiceInterface.ice
     components/TrajectoryPlayerInterface.ice
@@ -98,6 +96,11 @@ set(SLICE_FILES
 
     aron.ice
     armem.ice
+
+    components/ObstacleAvoidance/ObstacleAvoidanceInterface.ice
+    components/ObstacleAvoidance/ObstacleDetectionInterface.ice
+    components/ObstacleAvoidance/DSObstacleAvoidanceInterface.ice
+    components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice
 )
     #core/RobotIK.ice
 set(SLICE_FILES_ADDITIONAL_HEADERS
diff --git a/source/RobotAPI/interface/components/DSObstacleAvoidanceInterface.ice b/source/RobotAPI/interface/components/ObstacleAvoidance/DSObstacleAvoidanceInterface.ice
similarity index 55%
rename from source/RobotAPI/interface/components/DSObstacleAvoidanceInterface.ice
rename to source/RobotAPI/interface/components/ObstacleAvoidance/DSObstacleAvoidanceInterface.ice
index 13dead6ac09b9b1028c204e56bbc8e34285d065c..04176dc066828cfc28577851d556464880db076d 100644
--- a/source/RobotAPI/interface/components/DSObstacleAvoidanceInterface.ice
+++ b/source/RobotAPI/interface/components/ObstacleAvoidance/DSObstacleAvoidanceInterface.ice
@@ -28,8 +28,8 @@
 #include <ArmarXCore/interface/serialization/Eigen.ice>
 
 // RobotAPI
-#include <RobotAPI/interface/components/ObstacleAvoidanceInterface.ice>
-
+#include <RobotAPI/interface/components/ObstacleAvoidance/ObstacleAvoidanceInterface.ice>
+#include <RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.ice>
 
 module armarx
 {
@@ -49,51 +49,15 @@ module armarx
             double agent_safety_margin;
         };
 
-
-        struct Obstacle
-        {
-            string name;
-            double posX = 0;
-            double posY = 0;
-            double posZ = 0;
-            double yaw = 0;
-            double axisLengthX = 0;
-            double axisLengthY = 0;
-            double axisLengthZ = 0;
-            double refPosX = 0;
-            double refPosY = 0;
-            double refPosZ = 0;
-            double safetyMarginX = 0;
-            double safetyMarginY = 0;
-            double safetyMarginZ = 0;
-            double curvatureX = 1;
-            double curvatureY = 1;
-            double curvatureZ = 1;
-        };
-
-
-        sequence<dsobstacleavoidance::Obstacle> ObstacleList;
-
     };
 
 
-    interface DSObstacleAvoidanceInterface extends ObstacleAvoidanceInterface
+    interface DSObstacleAvoidanceInterface extends 
+	ObstacleAvoidanceInterface, ObstacleDetectionInterface
     {
 
-        dsobstacleavoidance::Config
-        getConfig();
-
-        void
-        updateObstacle(dsobstacleavoidance::Obstacle obstacle);
-
-        void
-        removeObstacle(string obstacle_name);
-
-        dsobstacleavoidance::ObstacleList
-        getObstacles();
-
-        void
-        updateEnvironment();
+        dsobstacleavoidance::Config 
+	getConfig();
 
         void
         writeDebugPlots(string filename);
diff --git a/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice b/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice
new file mode 100644
index 0000000000000000000000000000000000000000..9552091c342285ccbfe1be5603ed105a1708e792
--- /dev/null
+++ b/source/RobotAPI/interface/components/ObstacleAvoidance/DynamicObstacleManagerInterface.ice
@@ -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    Armar6Skills::ArmarXObjects::HumanAvoidance
+ * @author     Christian R. G. Dreher <c.dreher@kit.edu>
+ * @author     Fabian Peller
+ * @date       2019
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+// ArmarX
+#include <ArmarXCore/interface/serialization/Eigen.ice>
+
+
+module armarx
+{
+    interface DynamicObstacleManagerInterface
+    {
+        void
+        add_decayable_obstacle(Eigen::Vector2f e_origin, float e_rx, float e_ry, float e_yaw);
+
+        void
+        add_decayable_line_segment(Eigen::Vector2f line_start, Eigen::Vector2f line_end);
+
+        void
+        remove_all_decayable_obstacles();
+
+        void
+        directly_update_obstacle(string name, Eigen::Vector2f e_origin, float e_rx, float e_ry, float e_yaw);
+
+        void
+        remove_obstacle(string name);
+    };
+};
+
diff --git a/source/RobotAPI/interface/components/ObstacleAvoidanceInterface.ice b/source/RobotAPI/interface/components/ObstacleAvoidance/ObstacleAvoidanceInterface.ice
similarity index 100%
rename from source/RobotAPI/interface/components/ObstacleAvoidanceInterface.ice
rename to source/RobotAPI/interface/components/ObstacleAvoidance/ObstacleAvoidanceInterface.ice
diff --git a/source/RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.ice b/source/RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.ice
new file mode 100644
index 0000000000000000000000000000000000000000..0a0435b203c00767deeb7e52fc4af93244c3a080
--- /dev/null
+++ b/source/RobotAPI/interface/components/ObstacleAvoidance/ObstacleDetectionInterface.ice
@@ -0,0 +1,79 @@
+/*
+ * 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::ArmarXObjects::ObstacleAvoidance
+ * @author     Christian R. G. Dreher <c.dreher@kit.edu>
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+
+// ArmarX
+#include <ArmarXCore/interface/serialization/Eigen.ice>
+
+
+module armarx
+{
+
+    module obstacledetection
+	{
+
+		struct Obstacle
+		{
+			string name;
+			double posX = 0;
+			double posY = 0;
+			double posZ = 0;
+			double yaw = 0;
+			double axisLengthX = 0;
+			double axisLengthY = 0;
+			double axisLengthZ = 0;
+			double refPosX = 0;
+			double refPosY = 0;
+			double refPosZ = 0;
+			double safetyMarginX = 0;
+			double safetyMarginY = 0;
+			double safetyMarginZ = 0;
+			double curvatureX = 1;
+			double curvatureY = 1;
+			double curvatureZ = 1;
+		};
+
+        sequence<obstacledetection::Obstacle> ObstacleList;
+
+	};
+
+
+	interface ObstacleDetectionInterface
+	{
+		void
+        updateObstacle(obstacledetection::Obstacle obstacle);
+
+		void
+		removeObstacle(string obstacle_name);
+
+        obstacledetection::ObstacleList
+		getObstacles();
+
+		void
+		updateEnvironment();
+
+	};
+
+};