From 65d88f93385ce875aa541e77337db40594ce19fa Mon Sep 17 00:00:00 2001
From: Fabian Reister <fabian.reister@kit.edu>
Date: Sun, 11 Jul 2021 21:27:40 +0200
Subject: [PATCH] update

---
 .../components/Navigator/Navigator.cpp        | 110 ++++++++++++++----
 .../components/Navigator/Navigator.h          |   8 +-
 .../components/Navigator/RemoteGui.cpp        |  34 ++++--
 .../libraries/algorithms/CMakeLists.txt       |   6 +
 .../algorithms/astar/AStarPlanner.cpp         |   2 +
 .../smoothing/ChainApproximation.cpp          |   4 +-
 .../algorithms/smoothing/ChainApproximation.h |   4 +-
 .../smoothing/CircularPathSmoothing.cpp       |  82 +++++++++++++
 .../smoothing/CircularPathSmoothing.h         |  69 +----------
 .../client/NavigationStackConfig.cpp          |  24 ++--
 .../libraries/client/NavigationStackConfig.h  |   9 +-
 .../Navigation/libraries/core/Trajectory.cpp  |  73 +++++++++++-
 source/Navigation/libraries/core/Trajectory.h |  18 ++-
 source/Navigation/libraries/core/constants.h  |  26 +++--
 source/Navigation/libraries/core/fwd.h        |  33 ++++++
 source/Navigation/libraries/core/types.h      |   4 +
 .../factories/GlobalPlannerFactory.h          |   5 +-
 .../libraries/factories/LocalPlannerFactory.h |   6 +-
 .../factories/NavigationStackFactory.cpp      |  12 +-
 .../factories/NavigationStackFactory.h        |   4 +
 .../factories/SafetyControllerFactory.h       |   5 +-
 .../factories/TrajectoryControllerFactory.h   |   6 +-
 source/Navigation/libraries/factories/fwd.h   |  53 +++++++++
 .../libraries/global_planning/AStar.cpp       |  67 ++++++++++-
 .../libraries/global_planning/AStar.h         |   5 +
 .../libraries/global_planning/GlobalPlanner.h |   2 +-
 .../Navigation/libraries/server/Navigator.cpp |  79 ++++++++++---
 .../Navigation/libraries/server/Navigator.h   |   2 +
 .../server/monitoring/GoalReachedMonitor.cpp  |   7 +-
 29 files changed, 596 insertions(+), 163 deletions(-)
 create mode 100644 source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.cpp
 create mode 100644 source/Navigation/libraries/core/fwd.h
 create mode 100644 source/Navigation/libraries/factories/fwd.h

diff --git a/source/Navigation/components/Navigator/Navigator.cpp b/source/Navigation/components/Navigator/Navigator.cpp
index 4e0714af..f4ef750e 100644
--- a/source/Navigation/components/Navigator/Navigator.cpp
+++ b/source/Navigation/components/Navigator/Navigator.cpp
@@ -23,6 +23,7 @@
 
 #include "Navigator.h"
 
+#include <algorithm>
 #include <cmath>
 #include <iterator>
 #include <memory>
@@ -38,22 +39,20 @@
 #include "ArmarXCore/core/services/tasks/PeriodicTask.h"
 #include "ArmarXCore/core/services/tasks/TaskUtil.h"
 #include "ArmarXCore/util/CPPUtility/trace.h"
+#include <ArmarXCore/core/exceptions/LocalException.h>
+#include <ArmarXCore/core/logging/LogSender.h>
 
 #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
 
 #include "RobotAPI/libraries/core/remoterobot/RemoteRobot.h"
 
-// Navigation
-#include "AStar.h"
+#include "Navigation/components/Navigator/RemoteGui.h"
 #include "Navigation/libraries/client/NavigationStackConfig.h"
 #include "Navigation/libraries/core/types.h"
-// #include "Navigation/libraries/factories/NavigationStackFactory.h"
-// #include "Navigation/libraries/global_planning/Point2Point.h"
 #include "Navigation/libraries/server/Navigator.h"
 #include "Navigation/libraries/server/execution/PlatformUnitExecutor.h"
-// #include "Navigation/libraries/trajectory_control/TrajectoryFollowingController.h"
+#include "Navigation/libraries/factories/NavigationStackFactory.h"
 #include "Navigation/libraries/util/util.h"
-#include "RemoteGui.h"
 
 armarx::nav::components::Navigator::Navigator() = default;
 armarx::nav::components::Navigator::~Navigator() = default;
@@ -64,6 +63,15 @@ void armarx::nav::components::Navigator::onInitComponent()
 
 void armarx::nav::components::Navigator::onConnectComponent()
 {
+    static bool initialized{false};
+
+    // redirect to onReconnect to avoid any setup issues
+    if (initialized)
+    {
+        ARMARX_INFO << "Reconnecting ...";
+        onReconnectComponent();
+        return;
+    }
 
     // TODO check if reconnecting
 
@@ -77,16 +85,33 @@ void armarx::nav::components::Navigator::onConnectComponent()
     // TODO memory
     // TODO param (10)
 
-    robotStateUpdateTask = new PeriodicTask<Navigator>(this, &Navigator::updateRobot, 10);
+    robotStateUpdateTask = new PeriodicTask<Navigator>(
+        this, &Navigator::updateRobot, 10, false, "RobotStateUpdateTask");
     robotStateUpdateTask->start();
 
     navRemoteGui = std::make_unique<NavigatorRemoteGui>(remoteGui, *this);
     navRemoteGui->enable();
+
+    initialized = true;
+}
+
+void armarx::nav::components::Navigator::onReconnectComponent()
+{
+    robotStateUpdateTask->start();
+
+    // TODO not in all cases meaningful
+    resumeMovement();
+
+    navRemoteGui->enable();
 }
 
 void armarx::nav::components::Navigator::onDisconnectComponent()
 {
     robotStateUpdateTask->stop();
+
+    pauseMovement();
+
+    navRemoteGui->disable();
 }
 
 void armarx::nav::components::Navigator::onExitComponent()
@@ -142,12 +167,22 @@ void armarx::nav::components::Navigator::moveTo(const std::vector<Eigen::Matrix4
         const std::string& callerId,
         const Ice::Current&)
 {
-    // TODO: Error handling.
 
-    ARMARX_INFO << "MoveTo";
+    // ARMARX_INFO << LogSender::eGreen << "MoveTo";
 
-    navigators.at(callerId).moveTo(convert(waypoints),
-                                   core::NavigationFramesMap.from_name(navigationMode));
+    try
+    {
+        navigators.at(callerId).moveTo(convert(waypoints),
+                                       core::NavigationFramesMap.from_name(navigationMode));
+    }
+    catch (...)
+    {
+        // TODO: Error handling.
+        ARMARX_WARNING << "Failed to execute moveTo()."
+                       << "Movement will be paused.";
+        pauseMovement(); // TODO pause movement must not throw
+        throw;
+    }
 }
 
 void armarx::nav::components::Navigator::moveTowards(const Eigen::Vector3f& direction,
@@ -165,16 +200,28 @@ void armarx::nav::components::Navigator::moveTowards(const Eigen::Vector3f& dire
 
 void armarx::nav::components::Navigator::pauseMovement(const Ice::Current&)
 {
-    // TODO
-    //  find active navigator
-    //  pause navigator
+    auto* navigator = activeNavigator();
+
+    if (navigator == nullptr)
+    {
+        ARMARX_INFO << "No active navigator. Cannot pause movement!";
+        return;
+    }
+
+    navigator->pauseMovement();
 }
 
 void armarx::nav::components::Navigator::resumeMovement(const Ice::Current&)
 {
-    // TODO
-    //  find active navigator
-    //  resume navigator
+    auto* navigator = activeNavigator();
+
+    if (navigator == nullptr)
+    {
+        ARMARX_INFO << "No active navigator. Cannot resume movement!";
+        return;
+    }
+
+    navigator->resumeMovement();
 }
 
 armarx::PropertyDefinitionsPtr armarx::nav::components::Navigator::createPropertyDefinitions()
@@ -206,11 +253,11 @@ armarx::nav::core::StaticScene armarx::nav::components::Navigator::staticScene()
 {
     ARMARX_TRACE;
 
-    core::StaticScene scene;
-
-    objpose::ObjectPoseSeq objectPoses = ObjectPoseClientPluginUser::getObjectPoses();
-
-    scene.objects = util::asSceneObjects(objectPoses);
+    const objpose::ObjectPoseSeq objectPoses = ObjectPoseClientPluginUser::getObjectPoses();
+    core::StaticScene scene
+    {
+        .objects = util::asSceneObjects(objectPoses)
+    };
 
     ARMARX_INFO << "The scene consists of " << scene.objects->getSize() << " objects";
 
@@ -238,3 +285,22 @@ void armarx::nav::components::Navigator::updateRobot()
 {
     synchronizeLocalClone(scene.robot);
 }
+
+armarx::nav::server::Navigator* armarx::nav::components::Navigator::activeNavigator()
+{
+    const auto isActive = [](auto & nameNavPair) -> bool
+    {
+        server::Navigator& navigator = nameNavPair.second;
+        return navigator.isActive();
+    };
+
+    auto it = std::find_if(navigators.begin(), navigators.end(), isActive);
+
+    // no navigator active?
+    if (it == navigators.end())
+    {
+        return nullptr;
+    }
+
+    return &it->second;
+}
diff --git a/source/Navigation/components/Navigator/Navigator.h b/source/Navigation/components/Navigator/Navigator.h
index a6ba65f8..dc42e68e 100644
--- a/source/Navigation/components/Navigator/Navigator.h
+++ b/source/Navigation/components/Navigator/Navigator.h
@@ -46,7 +46,6 @@
 
 #include <Navigation/components/Navigator/NavigatorInterface.h>
 #include <Navigation/components/Navigator/RemoteGui.h>
-#include <Navigation/libraries/core/StaticScene.h>
 #include <Navigation/libraries/core/types.h>
 #include <Navigation/libraries/server/Navigator.h>
 #include <Navigation/libraries/server/execution/PlatformUnitExecutor.h>
@@ -114,6 +113,8 @@ namespace armarx::nav::components
         /// @see armarx::ManagedIceObject::onConnectComponent()
         void onConnectComponent() override;
 
+        void onReconnectComponent();
+
         /// @see armarx::ManagedIceObject::onDisconnectComponent()
         void onDisconnectComponent() override;
 
@@ -127,6 +128,8 @@ namespace armarx::nav::components
         VirtualRobot::RobotPtr getRobot();
         void updateRobot();
 
+        server::Navigator* activeNavigator();
+
     private:
         // TODO update context periodically
 
@@ -137,7 +140,7 @@ namespace armarx::nav::components
         core::Scene scene;
         std::optional<server::PlatformUnitExecutor> executor;
         std::optional<server::ArvizIntrospector> introspector;
-        std::map<std::string, server::Navigator> navigators;
+        std::unordered_map<std::string, server::Navigator> navigators;
 
         std::mutex propertiesMutex;
 
@@ -145,6 +148,7 @@ namespace armarx::nav::components
 
         // TODO maybe as optional, but requires some effort
         std::unique_ptr<NavigatorRemoteGui> navRemoteGui;
+
     };
 } // namespace armarx::nav::components
 
diff --git a/source/Navigation/components/Navigator/RemoteGui.cpp b/source/Navigation/components/Navigator/RemoteGui.cpp
index c07064aa..bddeb4b3 100644
--- a/source/Navigation/components/Navigator/RemoteGui.cpp
+++ b/source/Navigation/components/Navigator/RemoteGui.cpp
@@ -6,6 +6,7 @@
 #include "ArmarXCore/core/time/CycleUtil.h"
 #include "ArmarXCore/statechart/ParameterMapping.h"
 #include "ArmarXCore/util/CPPUtility/trace.h"
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 #include "ArmarXGui/libraries/RemoteGui/WidgetBuilder/IntegerWidgets.h"
 #include "ArmarXGui/libraries/RemoteGui/WidgetBuilder/LayoutWidgets.h"
@@ -43,10 +44,7 @@ namespace armarx::nav::components
 
     NavigatorRemoteGui::~NavigatorRemoteGui()
     {
-        if (runningTask->isRunning())
-        {
-            runningTask->stop();
-        }
+        shutdown();
     }
 
     void NavigatorRemoteGui::createRemoteGuiTab()
@@ -269,10 +267,32 @@ namespace armarx::nav::components
 
             ARMARX_TRACE;
 
-            navigator.moveTo(waypoints,
-                             core::NavigationFramesMap.to_name(core::NavigationFrames::Absolute),
-                             "NavigatorRemoteGui");
+            try
+            {
+                navigator.moveTo(
+                    waypoints,
+                    core::NavigationFramesMap.to_name(core::NavigationFrames::Absolute),
+                    "NavigatorRemoteGui");
+            }
+            catch (const armarx::LocalException& ex)
+            {
+                ARMARX_WARNING << LogSender::eYellow
+                               << "Failed moving to target. Reason: " << GetHandledExceptionString()
+                               << LogSender::eReset;
+            }
         };
+
+        if (tab.controlGroup.pauseButton.wasClicked())
+        {
+            ARMARX_INFO << "pauseMovement() from RemoteGUI requested";
+            navigator.pauseMovement();
+        }
+
+        if (tab.controlGroup.continueButton.wasClicked())
+        {
+            ARMARX_INFO << "resumeMovement() from RemoteGUI requested";
+            navigator.resumeMovement();
+        }
     }
 
     void NavigatorRemoteGui::shutdown()
diff --git a/source/Navigation/libraries/algorithms/CMakeLists.txt b/source/Navigation/libraries/algorithms/CMakeLists.txt
index 0e499126..c4ada721 100644
--- a/source/Navigation/libraries/algorithms/CMakeLists.txt
+++ b/source/Navigation/libraries/algorithms/CMakeLists.txt
@@ -15,12 +15,18 @@ armarx_add_library(
         ./astar/AStarPlanner.cpp
         ./astar/Node.cpp
         ./astar/Planner2D.cpp
+        # smoothing
+        ./smoothing/ChainApproximation.cpp
+        ./smoothing/CircularPathSmoothing.cpp
     HEADERS
         ./algorithms.h
         # A*
         ./astar/AStarPlanner.h
         ./astar/Node.h
         ./astar/Planner2D.h
+        # smoothing
+        ./smoothing/ChainApproximation.h
+        ./smoothing/CircularPathSmoothing.h
 )
 
 add_library(
diff --git a/source/Navigation/libraries/algorithms/astar/AStarPlanner.cpp b/source/Navigation/libraries/algorithms/astar/AStarPlanner.cpp
index 5e38e8a8..3c282fb1 100644
--- a/source/Navigation/libraries/algorithms/astar/AStarPlanner.cpp
+++ b/source/Navigation/libraries/algorithms/astar/AStarPlanner.cpp
@@ -200,9 +200,11 @@ namespace armarx::nav::algo::astar
         createUniformGrid();
         ARMARX_INFO << "Setting start node";
         NodePtr nodeStart = closestNode(start);
+        ARMARX_CHECK(fulfillsConstraints(nodeStart)) << "Start node in collision!";
 
         ARMARX_INFO << "Setting goal node";
         NodePtr nodeGoal = closestNode(goal);
+        ARMARX_CHECK(fulfillsConstraints(nodeGoal)) << "Goal node in collision!";
 
         std::vector<NodePtr> closedSet;
         std::vector<NodePtr> openSet;
diff --git a/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.cpp b/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.cpp
index db730742..32899a47 100644
--- a/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.cpp
+++ b/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.cpp
@@ -8,7 +8,7 @@
 #include "ArmarXCore/core/exceptions/LocalException.h"
 #include "ArmarXCore/core/exceptions/local/ExpressionException.h"
 
-namespace armarx
+namespace armarx::nav::algo
 {
 
     ChainApproximation::ChainApproximation(const Points& points, const Params& params) :
@@ -211,4 +211,4 @@ namespace armarx
 
         return str;
     }
-} // namespace armarx
+} // namespace armarx::nav::algo
diff --git a/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.h b/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.h
index 98448a13..e3673f3f 100644
--- a/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.h
+++ b/source/Navigation/libraries/algorithms/smoothing/ChainApproximation.h
@@ -24,7 +24,7 @@
 
 #include <Eigen/Core>
 
-namespace armarx
+namespace armarx::nav::algo
 {
 
     namespace detail
@@ -95,4 +95,4 @@ namespace armarx
         const Params params;
     };
 
-} // namespace armarx
+} // namespace armarx::nav::algo
diff --git a/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.cpp b/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.cpp
new file mode 100644
index 00000000..6785a034
--- /dev/null
+++ b/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.cpp
@@ -0,0 +1,82 @@
+#include "CircularPathSmoothing.h"
+
+namespace armarx::nav::algo
+{
+    // TODO move to Simox
+    float getAngleBetweenVectors(const Eigen::Vector2f& v1, const Eigen::Vector2f& v2)
+    {
+        // 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;
+    }
+
+    CircularPathSmoothing::Points CircularPathSmoothing::smooth(const Points& p)
+    {
+
+        Points points;
+
+        points.push_back(p.front());
+
+        // omit start and end
+        for (size_t i = 1; i < (p.size() - 1); i++)
+        {
+            const Eigen::Vector2f& prev = p.at(i - 1);
+            const Eigen::Vector2f& at = p.at(i);
+            const Eigen::Vector2f& next = p.at(i + 1);
+
+            // the largest radius for smoothing
+            const float maxRadius = std::min((prev - at).norm(), (next - at).norm());
+
+            const float radius = std::min(maxRadius, 300.F);
+
+            const Eigen::Vector2f vIn = (prev - at).normalized();
+            const Eigen::Vector2f vOut = (next - at).normalized();
+
+            // const float phiIn  = ::math::Helpers::Angle(vIn);
+            // const float phiOut = ::math::Helpers::Angle(vOut);
+
+            // const float phi = phiIn + (phiOut - phiIn) / 2;
+
+            // the angle between the lines
+            const float phi = getAngleBetweenVectors(vIn, vOut);
+
+            // const Eigen::Vector2f at_dir = Eigen::Rotation2Df(phi) * Eigen::Vector2f::UnitX();
+
+            // const float rho = - sign(v_in.y()*v_out.x() - v_in.x() * v_out.y());
+            // const float chi_0 = std::atan2(v_in.y(), v_in.x());
+            // const float chi_end = std::atan2(v_out.y(), v_out.x());
+
+            // const float l = radius * std::cos(phi / 2);
+            const float l = radius / std::tan(phi / 2);
+
+            points.push_back(at + Eigen::Vector2f(prev - at).normalized() * l);
+            // points.push_back(at);
+            points.push_back(at + Eigen::Vector2f(next - at).normalized() * l);
+
+            // Eigen::Vector2f dirAtToPrev = (prev - at).normalized();
+            // Eigen::Vector2f dirAtToNext = (next - at).normalized();
+
+            // Eigen::Vector2f center =
+            //     at + dirAtToPrev * l +
+            //     radius * Eigen::Vector2f(dirAtToPrev.y(), -dirAtToPrev.x());
+
+            // const float alpha_start =
+            //     math::Helpers::Angle(Eigen::Vector2f(dirAtToPrev.y(), -dirAtToPrev.x()));
+            // const float alpha_end =
+            //     math::Helpers::Angle(Eigen::Vector2f(-dirAtToNext.y(), dirAtToNext.x()));
+
+            // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_end) * Eigen::Vector2f::UnitX()));
+            // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_start + (alpha_start - alpha_end)/2) * Eigen::Vector2f::UnitX()));
+            // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_start) * Eigen::Vector2f::UnitX()));
+            // points.push_back(center);
+        }
+
+        points.push_back(p.back());
+
+        return points;
+    }
+} // namespace armarx::nav::algo
diff --git a/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.h b/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.h
index bbf27c97..672f7c2f 100644
--- a/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.h
+++ b/source/Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.h
@@ -22,6 +22,9 @@
 
 #pragma once
 
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
 namespace armarx::nav::algo
 {
 
@@ -34,71 +37,7 @@ namespace armarx::nav::algo
         using Points = std::vector<Point>;
 
         /// circular path smoothing
-        Points smooth(const Points& p)
-        {
-
-            Points points;
-
-            points.push_back(p.front());
-
-            // omit start and end
-            for (size_t i = 1; i < (p.size() - 1); i++)
-            {
-                const Eigen::Vector2f& prev = p.at(i - 1);
-                const Eigen::Vector2f& at   = p.at(i);
-                const Eigen::Vector2f& next = p.at(i + 1);
-
-                // the largest radius for smoothing
-                const float maxRadius = std::min((prev - at).norm(), (next - at).norm());
-
-                const float radius = std::min(maxRadius, 300.F);
-
-                const Eigen::Vector2f vIn  = (prev - at).normalized();
-                const Eigen::Vector2f vOut = (next - at).normalized();
-
-                // const float phiIn  = ::math::Helpers::Angle(vIn);
-                // const float phiOut = ::math::Helpers::Angle(vOut);
-
-                // const float phi = phiIn + (phiOut - phiIn) / 2;
-
-                // the angle between the lines
-                const float phi = getAngleBetweenVectors(vIn, vOut);
-
-                // const Eigen::Vector2f at_dir = Eigen::Rotation2Df(phi) * Eigen::Vector2f::UnitX();
-
-                // const float rho = - sign(v_in.y()*v_out.x() - v_in.x() * v_out.y());
-                // const float chi_0 = std::atan2(v_in.y(), v_in.x());
-                // const float chi_end = std::atan2(v_out.y(), v_out.x());
-
-                // const float l = radius * std::cos(phi / 2);
-                const float l = radius / std::tan(phi / 2);
-
-                points.push_back(at + Eigen::Vector2f(prev - at).normalized() * l);
-                // points.push_back(at);
-                points.push_back(at + Eigen::Vector2f(next - at).normalized() * l);
-
-                // Eigen::Vector2f dirAtToPrev = (prev - at).normalized();
-                // Eigen::Vector2f dirAtToNext = (next - at).normalized();
-
-                // Eigen::Vector2f center =
-                //     at + dirAtToPrev * l +
-                //     radius * Eigen::Vector2f(dirAtToPrev.y(), -dirAtToPrev.x());
-
-                // const float alpha_start =
-                //     math::Helpers::Angle(Eigen::Vector2f(dirAtToPrev.y(), -dirAtToPrev.x()));
-                // const float alpha_end =
-                //     math::Helpers::Angle(Eigen::Vector2f(-dirAtToNext.y(), dirAtToNext.x()));
-
-                // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_end) * Eigen::Vector2f::UnitX()));
-                // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_start + (alpha_start - alpha_end)/2) * Eigen::Vector2f::UnitX()));
-                // points.push_back(center + radius * Eigen::Vector2f(Eigen::Rotation2Df(alpha_start) * Eigen::Vector2f::UnitX()));
-                // points.push_back(center);
-            }
-
-            points.push_back(p.back());
-
-            return points;
-        }
+        Points smooth(const Points& p);
     };
 
 } // namespace armarx::nav::algo
diff --git a/source/Navigation/libraries/client/NavigationStackConfig.cpp b/source/Navigation/libraries/client/NavigationStackConfig.cpp
index b503f003..71e6ca15 100644
--- a/source/Navigation/libraries/client/NavigationStackConfig.cpp
+++ b/source/Navigation/libraries/client/NavigationStackConfig.cpp
@@ -1,8 +1,14 @@
 #include "NavigationStackConfig.h"
 
+#include <memory>
+
+#include "RobotAPI/libraries/aron/core/navigator/data/NavigatorFactory.h"
+#include "RobotAPI/libraries/aron/core/navigator/data/primitive/String.h"
 #include <RobotAPI/interface/aron/Aron.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
 
 #include "Navigation/libraries/core/constants.h"
+#include "Navigation/libraries/core/types.h"
 
 namespace armarx::nav::client
 {
@@ -20,12 +26,13 @@ namespace armarx::nav::client
                                 glob_plan::AlgorithmNames.to_name(params.algorithm())));
         element->addElement(core::PARAMS_KEY, params.toAron());
 
-        dict.addElement(core::GLOBAL_PLANNER, element);
+        dict.addElement(core::StackLayerNames.to_name(core::StackLayer::GlobalPlanner), element);
 
         return *this;
     }
 
-    NavigationStackConfig& NavigationStackConfig::configureLocalPlanner(const loc_plan::LocalPlannerParams& params)
+    NavigationStackConfig&
+    NavigationStackConfig::configureLocalPlanner(const loc_plan::LocalPlannerParams& params)
     {
         aron::datanavigator::DictNavigatorPtr element(new aron::datanavigator::DictNavigator);
         element->addElement(core::NAME_KEY,
@@ -33,12 +40,13 @@ namespace armarx::nav::client
                                 loc_plan::AlgorithmNames.to_name(params.algorithm())));
         element->addElement(core::PARAMS_KEY, params.toAron());
 
-        dict.addElement(core::LOCAL_PLANNER, element);
+        dict.addElement(core::StackLayerNames.to_name(core::StackLayer::LocalPlanner), element);
 
         return *this;
     }
 
-    NavigationStackConfig& NavigationStackConfig::configureTrajectoryController(const traj_ctrl::TrajectoryControllerParams& params)
+    NavigationStackConfig& NavigationStackConfig::configureTrajectoryController(
+        const traj_ctrl::TrajectoryControllerParams& params)
     {
         aron::datanavigator::DictNavigatorPtr element(new aron::datanavigator::DictNavigator);
         element->addElement(core::NAME_KEY,
@@ -46,12 +54,14 @@ namespace armarx::nav::client
                                 traj_ctrl::AlgorithmNames.to_name(params.algorithm())));
         element->addElement(core::PARAMS_KEY, params.toAron());
 
-        dict.addElement(core::TRAJECTORY_CONTROLLER, element);
+        dict.addElement(core::StackLayerNames.to_name(core::StackLayer::TrajectoryController),
+                        element);
 
         return *this;
     }
 
-    NavigationStackConfig& NavigationStackConfig::configureSafetyController(const safe_ctrl::SafetyControllerParams& params)
+    NavigationStackConfig& NavigationStackConfig::configureSafetyController(
+        const safe_ctrl::SafetyControllerParams& params)
     {
         aron::datanavigator::DictNavigatorPtr element(new aron::datanavigator::DictNavigator);
         element->addElement(core::NAME_KEY,
@@ -59,7 +69,7 @@ namespace armarx::nav::client
                                 safe_ctrl::AlgorithmNames.to_name(params.algorithm())));
         element->addElement(core::PARAMS_KEY, params.toAron());
 
-        dict.addElement(core::SAFETY_CONTROLLER, element);
+        dict.addElement(core::StackLayerNames.to_name(core::StackLayer::SafetyController), element);
 
         return *this;
     }
diff --git a/source/Navigation/libraries/client/NavigationStackConfig.h b/source/Navigation/libraries/client/NavigationStackConfig.h
index 84bd4b46..6f75af5d 100644
--- a/source/Navigation/libraries/client/NavigationStackConfig.h
+++ b/source/Navigation/libraries/client/NavigationStackConfig.h
@@ -24,18 +24,16 @@
 
 #include <memory>
 
-#include "RobotAPI/libraries/aron/core/navigator/data/NavigatorFactory.h"
-#include "RobotAPI/libraries/aron/core/navigator/data/primitive/String.h"
-#include <RobotAPI/interface/aron/Aron.h>
 #include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
+#include <RobotAPI/interface/aron/Aron.h>
 
 #include "Navigation/libraries/core/types.h"
-#include "Navigation/libraries/factories/NavigationStackFactory.h"
+
+// TODO remove these headers once ARON types are used as params
 #include "Navigation/libraries/global_planning/GlobalPlanner.h"
 #include "Navigation/libraries/local_planning/LocalPlanner.h"
 #include "Navigation/libraries/safety_control/SafetyController.h"
 #include "Navigation/libraries/trajectory_control/TrajectoryController.h"
-#include <type_traits>
 
 namespace armarx::nav::client
 {
@@ -56,7 +54,6 @@ namespace armarx::nav::client
         core::NavigationFrames navigationFrame = core::NavigationFrames::Absolute;
 
         virtual aron::datanavigator::DictNavigatorPtr toAron() const;
-
     };
 
     class NavigationStackConfig
diff --git a/source/Navigation/libraries/core/Trajectory.cpp b/source/Navigation/libraries/core/Trajectory.cpp
index b5a8d5de..d7d7168b 100644
--- a/source/Navigation/libraries/core/Trajectory.cpp
+++ b/source/Navigation/libraries/core/Trajectory.cpp
@@ -1,16 +1,46 @@
 #include "Trajectory.h"
 
 #include <algorithm>
+#include <cmath>
+#include <cstddef>
 #include <iterator>
 #include <limits>
 
+#include <Eigen/Core>
+#include <Eigen/Geometry>
+
+#include <wykobi.hpp>
+
+#include <VirtualRobot/math/Helpers.h>
 #include <VirtualRobot/math/LinearInterpolatedPose.h>
 
+#include "Navigation/libraries/conversions/eigen.h"
 #include "Navigation/libraries/core/types.h"
-#include "wykobi.hpp"
 
 namespace armarx::nav::core
 {
+
+    namespace conv
+    {
+
+        TrajectoryPoint toTrajectoryPoint(const Pose& pose)
+        {
+            return TrajectoryPoint{.waypoint = {.pose = pose}, .velocity = 0.F};
+        }
+
+        TrajectoryPoints toTrajectoryPoints(const Path& path)
+        {
+            TrajectoryPoints trajectoryPoints;
+            trajectoryPoints.reserve(path.size());
+
+            std::transform(
+                path.begin(), path.end(), std::back_inserter(trajectoryPoints), toTrajectoryPoint);
+
+            return trajectoryPoints;
+        }
+
+    } // namespace conv
+
     Projection Trajectory::getProjection(const Pose& pose,
                                          const VelocityInterpolations& velocityInterpolation) const
     {
@@ -82,4 +112,45 @@ namespace armarx::nav::core
 
         return positions;
     }
+
+    Trajectory Trajectory::FromPath(const Path& path)
+    {
+        return {conv::toTrajectoryPoints(path)};
+    }
+
+    Trajectory Trajectory::FromPath(const Pose& start, const Positions& waypoints, const Pose& goal)
+    {
+        // currently, only 2D version
+
+        Path path;
+        path.reserve(waypoints.size());
+
+        if (waypoints.empty())
+        {
+            return FromPath({start, goal});
+        }
+
+        const auto directedPose = [](const Position & position, const Position & target) -> Pose
+        {
+            const Direction direction = target - position;
+
+            const float yaw = math::Helpers::Angle(nav::conv::to2D(direction));
+
+            // our robot is moving into y direction ( y is forward ... )
+            const Eigen::Rotation2Df R = Eigen::Rotation2Df(yaw) * Eigen::Rotation2Df(-M_PI_2f32);
+
+            return nav::conv::to3D(Eigen::Translation2f(nav::conv::to2D(position)) * R);
+        };
+
+        // insert waypoints pointing to next waypoint
+        for (size_t i = 0; i < waypoints.size() - 1; i++)
+        {
+            path.emplace_back(directedPose(waypoints.at(i), waypoints.at(i + 1)));
+        }
+
+        path.emplace_back(directedPose(waypoints.back(), goal.translation()));
+        path.push_back(goal);
+
+        return FromPath(path);
+    }
 } // namespace armarx::nav::core
diff --git a/source/Navigation/libraries/core/Trajectory.h b/source/Navigation/libraries/core/Trajectory.h
index 59e6d4ca..b875ba8f 100644
--- a/source/Navigation/libraries/core/Trajectory.h
+++ b/source/Navigation/libraries/core/Trajectory.h
@@ -22,6 +22,7 @@
 
 #pragma once
 
+#include <memory>
 #include "Navigation/libraries/core/types.h"
 
 namespace armarx::nav::core
@@ -33,6 +34,8 @@ namespace armarx::nav::core
         float velocity;
     };
 
+    using TrajectoryPoints = std::vector<TrajectoryPoint>;
+
     struct Projection
     {
         TrajectoryPoint projection;
@@ -47,6 +50,10 @@ namespace armarx::nav::core
         LastWaypoint
     };
 
+    class Trajectory;
+    using TrajectoryPtr = std::shared_ptr<Trajectory>;
+
+
     class Trajectory
     {
     public:
@@ -59,10 +66,19 @@ namespace armarx::nav::core
 
         [[nodiscard]] std::vector<Eigen::Vector3f> positions() const;
 
+        //! Note: the velocity will not be set!
+        // currently, only 2D version
+        // y is pointing forward
+        static Trajectory FromPath(const Path& path);
+
+        //! Note: the velocity will not be set!
+        // currently, only 2D version
+        // y is pointing forward
+        static Trajectory FromPath(const Pose& start, const Positions& waypoints, const Pose& goal);
+
     private:
         std::vector<TrajectoryPoint> points;
     };
 
-    using TrajectoryPtr = std::shared_ptr<Trajectory>;
 
 } // namespace armarx::nav::core
diff --git a/source/Navigation/libraries/core/constants.h b/source/Navigation/libraries/core/constants.h
index e904f386..192b440d 100644
--- a/source/Navigation/libraries/core/constants.h
+++ b/source/Navigation/libraries/core/constants.h
@@ -22,16 +22,28 @@
 
 #pragma once
 
+#include <SimoxUtility/meta/enum/EnumNames.hpp>
+
 namespace armarx::nav::core
 {
 
-    const std::string NAME_KEY = "name";
-    const std::string PARAMS_KEY = "params";
+    const inline std::string NAME_KEY = "name";
+    const inline std::string PARAMS_KEY = "params";
+
+    enum class StackLayer
+    {
+        GlobalPlanner,
+        LocalPlanner,
+        TrajectoryController,
+        SafetyController
+    };
+
+    const inline simox::meta::EnumNames<StackLayer> StackLayerNames
+    {
+        {StackLayer::GlobalPlanner, "GlobalPlanner"},
+        {StackLayer::LocalPlanner, "LocalPlanner"},
+        {StackLayer::TrajectoryController, "TrajectoryController"},
+        {StackLayer::SafetyController, "SafetyController"}};
 
-    // TODO enum
-    const std::string GLOBAL_PLANNER = "global_planner";
-    const std::string LOCAL_PLANNER = "local_planner";
-    const std::string TRAJECTORY_CONTROLLER = "trajectory_controller";
-    const std::string SAFETY_CONTROLLER = "safety_controller";
 
 } // namespace armarx::nav::core
diff --git a/source/Navigation/libraries/core/fwd.h b/source/Navigation/libraries/core/fwd.h
new file mode 100644
index 00000000..75cacf99
--- /dev/null
+++ b/source/Navigation/libraries/core/fwd.h
@@ -0,0 +1,33 @@
+/*
+ * 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/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+namespace armarx::nav::core
+{
+    struct Scene;
+    struct StaticScene;
+    struct DynamicScene;
+
+    struct Waypoint;
+    struct Twist;
+
+} // namespace armarx::nav::core
diff --git a/source/Navigation/libraries/core/types.h b/source/Navigation/libraries/core/types.h
index 4fa5945a..123916ff 100644
--- a/source/Navigation/libraries/core/types.h
+++ b/source/Navigation/libraries/core/types.h
@@ -50,6 +50,7 @@ namespace armarx::nav::core
     using Pose = Eigen::Isometry3f;
     using Pose2D = Eigen::Isometry2f;
 
+    using Position = Eigen::Vector3f;
     using Direction = Eigen::Vector3f;
 
     using Rotation = Eigen::Matrix3f;
@@ -57,6 +58,9 @@ namespace armarx::nav::core
     using LinearVelocity = Eigen::Vector3f;
     using AngularVelocity = Eigen::Vector3f;
 
+    using Path = std::vector<Pose>;
+    using Positions = std::vector<Position>;
+
     struct Twist
     {
         LinearVelocity linear;
diff --git a/source/Navigation/libraries/factories/GlobalPlannerFactory.h b/source/Navigation/libraries/factories/GlobalPlannerFactory.h
index 9c76caad..79f13300 100644
--- a/source/Navigation/libraries/factories/GlobalPlannerFactory.h
+++ b/source/Navigation/libraries/factories/GlobalPlannerFactory.h
@@ -22,7 +22,10 @@
 
 #pragma once
 
-#include "Navigation/libraries/global_planning/GlobalPlanner.h"
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
+
+#include "Navigation/libraries/core/fwd.h"
+#include "Navigation/libraries/factories/fwd.h"
 
 namespace armarx::nav::fac
 {
diff --git a/source/Navigation/libraries/factories/LocalPlannerFactory.h b/source/Navigation/libraries/factories/LocalPlannerFactory.h
index 1b1d944f..e6bb7b5f 100644
--- a/source/Navigation/libraries/factories/LocalPlannerFactory.h
+++ b/source/Navigation/libraries/factories/LocalPlannerFactory.h
@@ -22,9 +22,11 @@
 
 #pragma once
 
-#include "RobotAPI/libraries/aron/core/navigator/data/container/Dict.h"
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
+
+#include "Navigation/libraries/core/fwd.h"
+#include "Navigation/libraries/factories/fwd.h"
 
-#include "Navigation/libraries/local_planning/LocalPlanner.h"
 namespace armarx::nav::fac
 {
 
diff --git a/source/Navigation/libraries/factories/NavigationStackFactory.cpp b/source/Navigation/libraries/factories/NavigationStackFactory.cpp
index 037b52fc..95bac2d7 100644
--- a/source/Navigation/libraries/factories/NavigationStackFactory.cpp
+++ b/source/Navigation/libraries/factories/NavigationStackFactory.cpp
@@ -16,8 +16,10 @@ namespace armarx::nav::fac
         using aron::datanavigator::DictNavigator;
 
         const auto getElementOrNull =
-            [&params](const std::string & key) -> DictNavigator::PointerType
+            [&params](const core::StackLayer & layer) -> DictNavigator::PointerType
         {
+            const std::string key = core::StackLayerNames.to_name(layer);
+
             if (params->hasElement(key))
             {
                 return DictNavigator::DynamicCast(params->getElement(key));
@@ -28,10 +30,10 @@ namespace armarx::nav::fac
             return nullptr;
         };
 
-        const auto globalPlannerCfg = getElementOrNull(core::GLOBAL_PLANNER);
-        const auto localPlannerCfg = getElementOrNull(core::LOCAL_PLANNER);
-        const auto trajectoryControllerCfg = getElementOrNull(core::TRAJECTORY_CONTROLLER);
-        const auto safetyControllerCfg = getElementOrNull(core::SAFETY_CONTROLLER);
+        const auto globalPlannerCfg = getElementOrNull(core::StackLayer::GlobalPlanner);
+        const auto localPlannerCfg = getElementOrNull(core::StackLayer::LocalPlanner);
+        const auto trajectoryControllerCfg = getElementOrNull(core::StackLayer::TrajectoryController);
+        const auto safetyControllerCfg = getElementOrNull(core::StackLayer::SafetyController);
 
         return server::NavigationStack
         {
diff --git a/source/Navigation/libraries/factories/NavigationStackFactory.h b/source/Navigation/libraries/factories/NavigationStackFactory.h
index d7e7a8d4..6f1abf59 100644
--- a/source/Navigation/libraries/factories/NavigationStackFactory.h
+++ b/source/Navigation/libraries/factories/NavigationStackFactory.h
@@ -23,6 +23,10 @@
 #pragma once
 
 #include "Navigation/libraries/server/NavigationStack.h"
+#include "RobotAPI/libraries/aron/core/navigator/data/container/Dict.h"
+
+#include "Navigation/libraries/core/fwd.h"
+
 namespace armarx::nav::fac
 {
     /**
diff --git a/source/Navigation/libraries/factories/SafetyControllerFactory.h b/source/Navigation/libraries/factories/SafetyControllerFactory.h
index c31bdebc..2b9bb629 100644
--- a/source/Navigation/libraries/factories/SafetyControllerFactory.h
+++ b/source/Navigation/libraries/factories/SafetyControllerFactory.h
@@ -22,9 +22,10 @@
 
 #pragma once
 
-#include "RobotAPI/libraries/aron/core/navigator/data/container/Dict.h"
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
 
-#include "Navigation/libraries/safety_control/SafetyController.h"
+#include "Navigation/libraries/core/fwd.h"
+#include "Navigation/libraries/factories/fwd.h"
 
 namespace armarx::nav::fac
 {
diff --git a/source/Navigation/libraries/factories/TrajectoryControllerFactory.h b/source/Navigation/libraries/factories/TrajectoryControllerFactory.h
index d00ac6b5..cd12eeb8 100644
--- a/source/Navigation/libraries/factories/TrajectoryControllerFactory.h
+++ b/source/Navigation/libraries/factories/TrajectoryControllerFactory.h
@@ -22,10 +22,10 @@
 
 #pragma once
 
-#include "RobotAPI/libraries/aron/core/navigator/data/container/Dict.h"
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
 
-#include "Navigation/libraries/core/types.h"
-#include "Navigation/libraries/trajectory_control/TrajectoryController.h"
+#include "Navigation/libraries/core/fwd.h"
+#include "Navigation/libraries/factories/fwd.h"
 
 namespace armarx::nav::fac
 {
diff --git a/source/Navigation/libraries/factories/fwd.h b/source/Navigation/libraries/factories/fwd.h
new file mode 100644
index 00000000..adb54ba3
--- /dev/null
+++ b/source/Navigation/libraries/factories/fwd.h
@@ -0,0 +1,53 @@
+/*
+ * 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/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace armarx::nav
+{
+
+    namespace glob_plan
+    {
+        class GlobalPlanner;
+        using GlobalPlannerPtr = std::shared_ptr<GlobalPlanner>;
+    } // namespace glob_plan
+
+    namespace loc_plan
+    {
+        class LocalPlanner;
+        using LocalPlannerPtr = std::shared_ptr<LocalPlanner>;
+    } // namespace loc_plan
+
+    namespace traj_ctrl
+    {
+        class TrajectoryController;
+        using TrajectoryControllerPtr = std::shared_ptr<TrajectoryController>;
+    } // namespace traj_ctrl
+
+    namespace safe_ctrl
+    {
+        class SafetyController;
+        using SafetyControllerPtr = std::shared_ptr<SafetyController>;
+    } // namespace safe_ctrl
+
+} // namespace armarx::nav
diff --git a/source/Navigation/libraries/global_planning/AStar.cpp b/source/Navigation/libraries/global_planning/AStar.cpp
index 523e9f83..59e55675 100644
--- a/source/Navigation/libraries/global_planning/AStar.cpp
+++ b/source/Navigation/libraries/global_planning/AStar.cpp
@@ -1,6 +1,15 @@
 #include "AStar.h"
 
-#include "Navigation/libraries/algorithms/astar/AStarPlanner.h"
+#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include "Navigation/libraries/global_planning/Point2Point.h"
+#include <Navigation/libraries/algorithms/astar/AStarPlanner.h>
+#include <Navigation/libraries/algorithms/smoothing/ChainApproximation.h>
+#include <Navigation/libraries/algorithms/smoothing/CircularPathSmoothing.h>
+#include <Navigation/libraries/conversions/eigen.h>
+#include <Navigation/libraries/core/Trajectory.h>
 #include <Navigation/libraries/global_planning/aron/AStarParams.aron.generated.h>
 
 namespace armarx::nav::glob_plan
@@ -30,16 +39,64 @@ namespace armarx::nav::glob_plan
     {
     }
 
+    auto robotCollisionModel()
+    {
+        VirtualRobot::CoinVisualizationFactory factory;
+        const auto cylinder = factory.createCylinder(1500.F / 2, 2000.F);
+
+        VirtualRobot::CollisionModelPtr collisionModel(new VirtualRobot::CollisionModel(cylinder));
+
+        return collisionModel;
+    }
+
+    std::vector<Eigen::Vector2f> AStar::postProcessPath(const std::vector<Eigen::Vector2f>& path)
+    {
+        /// chain approximation
+        algo::ChainApproximation approx(path,
+                                        algo::ChainApproximation::Params{.distanceTh = 200.F});
+        approx.approximate();
+        const auto p = approx.approximatedChain();
+
+        // visualizePath(p, "approximated", simox::Color::green());
+
+        algo::CircularPathSmoothing smoothing;
+        const auto points = smoothing.smooth(p);
+
+        return points;
+    }
+
     core::TrajectoryPtr AStar::plan(const core::Pose& goal)
     {
+        ARMARX_TRACE;
+
         algo::astar::AStarPlanner planner(scene.robot, scene.staticScene->objects, 100.f);
         // planner.setRobotColModel("Platform-colmodel");
 
-        // TODO!
-        // planner.setRobotCollisionModel(robotCollisionModel());
+        // planner.setRobotColModel("Platform-colmodel");
+        planner.setRobotCollisionModel(robotCollisionModel());
+
+        const Eigen::Vector2f startPos = conv::to2D(scene.robot->getGlobalPosition());
+        const Eigen::Vector2f goalPos = conv::to2D(goal.translation());
+
+        const auto timeStart = IceUtil::Time::now();
+        const auto plan = planner.plan(startPos, goalPos);
+        const auto timeEnd = IceUtil::Time::now();
+
+        ARMARX_IMPORTANT << "A* planning took " << (timeEnd - timeStart).toMilliSeconds() << " ms";
+        ARMARX_IMPORTANT << "Path contains " << plan.size() << " points";
+
+        auto smoothPlan = postProcessPath(plan);
+        ARMARX_IMPORTANT << "Smooth path contains " << smoothPlan.size() << " points";
+
+        // we need to strip the first and the last points from the plan as they encode the start and goal position
+        smoothPlan.erase(plan.begin());
+        smoothPlan.pop_back();
 
-        // TODO
-        return {};
+        ARMARX_TRACE;
+        auto trajectory = core::Trajectory::FromPath(
+                              core::Pose(scene.robot->getGlobalPose()), conv::to3D(smoothPlan), goal);
 
+        ARMARX_TRACE;
+        return std::make_shared<core::Trajectory>(trajectory);
     }
 } // namespace armarx::nav::glob_plan
diff --git a/source/Navigation/libraries/global_planning/AStar.h b/source/Navigation/libraries/global_planning/AStar.h
index 5a78af3d..42bfa012 100644
--- a/source/Navigation/libraries/global_planning/AStar.h
+++ b/source/Navigation/libraries/global_planning/AStar.h
@@ -45,9 +45,14 @@ namespace armarx::nav::glob_plan
     {
     public:
         AStar(const AStarParams& params, const core::Scene& ctx);
+        ~AStar() override = default;
 
         core::TrajectoryPtr plan(const core::Pose& goal) override;
 
+    protected:
+        std::vector<Eigen::Vector2f> postProcessPath(const std::vector<Eigen::Vector2f>& path);
+
+    private:
         AStarParams params;
     };
 
diff --git a/source/Navigation/libraries/global_planning/GlobalPlanner.h b/source/Navigation/libraries/global_planning/GlobalPlanner.h
index 216e5167..927600d7 100644
--- a/source/Navigation/libraries/global_planning/GlobalPlanner.h
+++ b/source/Navigation/libraries/global_planning/GlobalPlanner.h
@@ -30,7 +30,7 @@
 #include "Navigation/libraries/core/StaticScene.h"
 #include "Navigation/libraries/core/Trajectory.h"
 #include "Navigation/libraries/core/types.h"
-#include "core.h"
+#include "Navigation/libraries/global_planning/core.h"
 
 namespace armarx::nav::glob_plan
 {
diff --git a/source/Navigation/libraries/server/Navigator.cpp b/source/Navigation/libraries/server/Navigator.cpp
index 3a2e0fdc..193caad2 100644
--- a/source/Navigation/libraries/server/Navigator.cpp
+++ b/source/Navigation/libraries/server/Navigator.cpp
@@ -11,12 +11,19 @@
 #include "ArmarXCore/core/logging/Logging.h"
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
-#include "monitoring/GoalReachedMonitor.h"
+#include "Navigation/libraries/server/monitoring/GoalReachedMonitor.h"
 #include <Navigation/libraries/core/types.h>
 #include <Navigation/libraries/server/StackResult.h>
 
 namespace armarx::nav::server
 {
+    void stopIfRunning(PeriodicTask<Navigator>::pointer_type& task)
+    {
+        if (task)
+        {
+            task->stop();
+        }
+    }
 
     Navigator::Navigator(const NavigatorConfig& config) : config(config)
     {
@@ -28,6 +35,13 @@ namespace armarx::nav::server
     {
         ARMARX_INFO << "Navigator destructor";
         pauseMovement();
+
+        stopIfRunning(localPlannerTask);
+        stopIfRunning(trajectoryControllerTask);
+        stopIfRunning(safetyControllerTask);
+        stopIfRunning(executorTask);
+        stopIfRunning(introspectorTask);
+        stopIfRunning(monitorTask);
     }
 
     void Navigator::moveTo(const std::vector<core::Pose>& waypoints,
@@ -62,6 +76,8 @@ namespace armarx::nav::server
         // TODO plan on multiple waypoints
         res.globalTrajectory = config.stack.globalPlanner->plan(core::Pose(waypoints.at(0)));
 
+        ARMARX_INFO << "Global planning completed. Will now start all required threads";
+
         // local planner
         if (config.stack.localPlanner)
         {
@@ -69,7 +85,9 @@ namespace armarx::nav::server
             localPlannerTask =
                 new PeriodicTask<Navigator>(this,
                                             &Navigator::updateLocalPlanner,
-                                            config.general.tasks.localPlanningUpdatePeriod);
+                                            config.general.tasks.localPlanningUpdatePeriod,
+                                            false,
+                                            "LocalPlannerTask");
             localPlannerTask->start();
         }
 
@@ -78,7 +96,9 @@ namespace armarx::nav::server
         trajectoryControllerTask =
             new PeriodicTask<Navigator>(this,
                                         &Navigator::updateTrajectoryController,
-                                        config.general.tasks.trajectoryControllerUpdatePeriod);
+                                        config.general.tasks.trajectoryControllerUpdatePeriod,
+                                        false,
+                                        "TrajectoryControllerTask");
         trajectoryControllerTask->start();
 
         // safety controller
@@ -88,26 +108,41 @@ namespace armarx::nav::server
             safetyControllerTask =
                 new PeriodicTask<Navigator>(this,
                                             &Navigator::updateSafetyController,
-                                            config.general.tasks.safetyControllerUpdatePeriod);
+                                            config.general.tasks.safetyControllerUpdatePeriod,
+                                            false,
+                                            "SafetyControllerTask");
             safetyControllerTask->start();
         }
 
         // executor
-        executorTask = new PeriodicTask<Navigator>(
-            this, &Navigator::updateExecutor, config.general.tasks.executorUpdatePeriod);
+        executorTask = new PeriodicTask<Navigator>(this,
+                &Navigator::updateExecutor,
+                config.general.tasks.executorUpdatePeriod,
+                false,
+                "ExecutorTask");
         executorTask->start();
 
         // introspector
-        introspectorTask = new PeriodicTask<Navigator>(
-            this, &Navigator::updateIntrospector, config.general.tasks.introspectorUpdatePeriod);
+        introspectorTask =
+            new PeriodicTask<Navigator>(this,
+                                        &Navigator::updateIntrospector,
+                                        config.general.tasks.introspectorUpdatePeriod,
+                                        false,
+                                        "IntrospectorTask");
         introspectorTask->start();
 
         // monitoring
         goalReachedMonitor =
             GoalReachedMonitor(waypoints, *config.scene, GoalReachedMonitorConfig());
-        monitorTask = new PeriodicTask<Navigator>(
-            this, &Navigator::updateMonitor, config.general.tasks.monitorUpdatePeriod);
+        monitorTask = new PeriodicTask<Navigator>(this,
+                &Navigator::updateMonitor,
+                config.general.tasks.monitorUpdatePeriod,
+                false,
+                "MonitorTask");
         monitorTask->start();
+
+        // could be false if pauseMovement has been called in the past
+        movementEnabled.store(true);
     }
 
     void Navigator::moveTowards(const core::Direction& direction,
@@ -180,20 +215,20 @@ namespace armarx::nav::server
 
     void Navigator::updateMonitor()
     {
-        if (goalReachedMonitor->goalReached())
+        if (goalReachedMonitor->goalReached() and movementEnabled.load())
         {
             // [[unlikely]]
 
             ARMARX_INFO << "Goal reached!";
             movementEnabled.store(false);
 
-            // stop all threads, including this one
-            localPlannerTask->stop();
-            trajectoryControllerTask->stop();
-            safetyControllerTask->stop();
-            executorTask->stop();
-            introspectorTask->stop();
-            monitorTask->stop();
+            // stop all threads, excluding this one
+            stopIfRunning(localPlannerTask);
+            stopIfRunning(trajectoryControllerTask);
+            stopIfRunning(safetyControllerTask);
+            stopIfRunning(executorTask);
+            stopIfRunning(introspectorTask);
+            // monitorTask->stop();
         }
     }
 
@@ -248,6 +283,8 @@ namespace armarx::nav::server
     {
         movementEnabled.store(false);
         const core::Twist zero{Eigen::Vector3f::Zero(), Eigen::Vector3f::Zero()};
+
+        ARMARX_CHECK_NOT_NULL(config.executor);
         config.executor->move(zero);
     }
 
@@ -256,6 +293,12 @@ namespace armarx::nav::server
         movementEnabled.store(true);
     }
 
+    bool Navigator::isActive() const noexcept
+    {
+        // TODO maybe need to check other stuff
+        return movementEnabled;
+    }
+
     Navigator::Navigator(Navigator&& other) noexcept :
         config{std::move(other.config)}, movementEnabled{other.movementEnabled.load()}
     {
diff --git a/source/Navigation/libraries/server/Navigator.h b/source/Navigation/libraries/server/Navigator.h
index 514d5976..9a5852fc 100644
--- a/source/Navigation/libraries/server/Navigator.h
+++ b/source/Navigation/libraries/server/Navigator.h
@@ -83,6 +83,8 @@ namespace armarx::nav::server
         void pauseMovement();
         void resumeMovement();
 
+        bool isActive() const noexcept;
+
         // // Non-API
         Navigator(Navigator&& other) noexcept;
         virtual ~Navigator();
diff --git a/source/Navigation/libraries/server/monitoring/GoalReachedMonitor.cpp b/source/Navigation/libraries/server/monitoring/GoalReachedMonitor.cpp
index d044f43a..d7c70957 100644
--- a/source/Navigation/libraries/server/monitoring/GoalReachedMonitor.cpp
+++ b/source/Navigation/libraries/server/monitoring/GoalReachedMonitor.cpp
@@ -1,15 +1,14 @@
 #include "GoalReachedMonitor.h"
 
 #include <VirtualRobot/Robot.h>
-
-#include <exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 namespace armarx::nav::server
 {
 
     GoalReachedMonitor::GoalReachedMonitor(const std::vector<core::Pose>& waypoints,
-                                                 const core::Scene& scene,
-                                                 const GoalReachedMonitorConfig& config) :
+                                           const core::Scene& scene,
+                                           const GoalReachedMonitorConfig& config) :
         waypoints(waypoints), scene(scene), config(config)
     {
         ARMARX_CHECK(not waypoints.empty());
-- 
GitLab