diff --git a/CMakeLists.txt b/CMakeLists.txt
index 308bddb12bbc1dd0968f0348b19024e6c6bf35c0..fc6e0627c607299fc0eaa0b6a8f6a1103cc28dd8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,8 @@ armarx_find_package(PUBLIC VTK QUIET)
 armarx_find_package(PUBLIC SemanticObjectRelations QUIET)
 armarx_find_package(PUBLIC OpenCV QUIET)  # Required as RobotAPI is a legacy project.
 armarx_find_package(PUBLIC range-v3 QUIET)
+armarx_find_package(PUBLIC HRVO QUIET)
+armarx_find_package(PUBLIC RVO QUIET)
 
 # human aware navigation
 armarx_find_package(PUBLIC teb_local_planner QUIET)
diff --git a/scenarios/HumanAwareNavigation/config/example_client.cfg b/scenarios/HumanAwareNavigation/config/example_client.cfg
index c21733bd95c226d102ba54430e01dc8b8b848766..ea5576f65c6fdb7ec47b104bf675aa5e3558ce75 100644
--- a/scenarios/HumanAwareNavigation/config/example_client.cfg
+++ b/scenarios/HumanAwareNavigation/config/example_client.cfg
@@ -194,6 +194,22 @@ ArmarX.ExampleClient.nav.NavigatorName = navigator
 # ArmarX.example_client.ObjectName = ""
 
 
+# ArmarX.example_client.mem.nav.costmap.CoreSegment:  
+#  Attributes:
+#  - Default:            Costmap
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.example_client.mem.nav.costmap.CoreSegment = Costmap
+
+
+# ArmarX.example_client.mem.nav.costmap.Memory:  
+#  Attributes:
+#  - Default:            Navigation
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.example_client.mem.nav.costmap.Memory = Navigation
+
+
 # ArmarX.example_client.mem.robot_state.Memory:  
 #  Attributes:
 #  - Default:            RobotState
@@ -233,7 +249,7 @@ ArmarX.ExampleClient.nav.NavigatorName = navigator
 #  - Default:            standard
 #  - Case sensitivity:   yes
 #  - Required:           no
-#  - Possible values: {complex, point_to_point, standard, update_navigator}
+#  - Possible values: {complex, point_to_point, standard, update_navigator, wander_around}
 # ArmarX.example_client.mode = standard
 
 
diff --git a/scenarios/HumanAwareNavigation/config/human_simulator.cfg b/scenarios/HumanAwareNavigation/config/human_simulator.cfg
index c0a571fa5e9de5a86f9fecf99428a7334f2302f8..d7720e7bf82f9ffc176e204cfefd69ebf243f3f3 100644
--- a/scenarios/HumanAwareNavigation/config/human_simulator.cfg
+++ b/scenarios/HumanAwareNavigation/config/human_simulator.cfg
@@ -157,7 +157,23 @@
 #  - Case sensitivity:   yes
 #  - Required:           no
 #  - Possible values: {Debug, Error, Fatal, Important, Info, Undefined, Verbose, Warning}
-# ArmarX.Verbosity = Info
+ArmarX.Verbosity = Verbose
+
+
+# ArmarX.human_simulator.ArVizStorageName:  Name of the ArViz storage
+#  Attributes:
+#  - Default:            ArVizStorage
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.human_simulator.ArVizStorageName = ArVizStorage
+
+
+# ArmarX.human_simulator.ArVizTopicName:  Name of the ArViz topic
+#  Attributes:
+#  - Default:            ArVizTopic
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.human_simulator.ArVizTopicName = ArVizTopic
 
 
 # ArmarX.human_simulator.EnableProfiling:  enable profiler which is used for logging performance events
@@ -178,6 +194,14 @@
 # ArmarX.human_simulator.MinimumLoggingLevel = Undefined
 
 
+# ArmarX.human_simulator.ObjectMemoryName:  Name of the object memory.
+#  Attributes:
+#  - Default:            ObjectMemory
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.human_simulator.ObjectMemoryName = ObjectMemory
+
+
 # ArmarX.human_simulator.ObjectName:  Name of IceGrid well-known object
 #  Attributes:
 #  - Default:            ""
@@ -260,12 +284,28 @@
 # ArmarX.human_simulator.mns.MemoryNameSystemName = MemoryNameSystem
 
 
+# ArmarX.human_simulator.p.human.goalDistanceThreshold:  
+#  Attributes:
+#  - Default:            100
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.human_simulator.p.human.goalDistanceThreshold = 100
+
+
+# ArmarX.human_simulator.p.human.maxLinearVelocity:  
+#  Attributes:
+#  - Default:            200
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.human_simulator.p.human.maxLinearVelocity = 200
+
+
 # ArmarX.human_simulator.p.nHumans:  Number of humans to spawn.
 #  Attributes:
 #  - Default:            4
 #  - Case sensitivity:   yes
 #  - Required:           no
-# ArmarX.human_simulator.p.nHumans = 4
+ArmarX.human_simulator.p.nHumans = 6
 
 
 # ArmarX.human_simulator.p.taskPeriodMs:  
diff --git a/scenarios/HumanAwareNavigation/config/navigation_memory.cfg b/scenarios/HumanAwareNavigation/config/navigation_memory.cfg
index a3e73f4f38e5be8e1545891322ab2ac4f66b7471..45901d4483977812ccf754fd73b2d6ce7fd8a3c7 100644
--- a/scenarios/HumanAwareNavigation/config/navigation_memory.cfg
+++ b/scenarios/HumanAwareNavigation/config/navigation_memory.cfg
@@ -255,10 +255,10 @@ ArmarX.navigation_memory.MinimumLoggingLevel = Verbose
 
 # ArmarX.navigation_memory.p.locationGraph.visuFrequency:  Visualization frequeny of locations and graph edges [Hz].
 #  Attributes:
-#  - Default:            2
+#  - Default:            10
 #  - Case sensitivity:   yes
 #  - Required:           no
-# ArmarX.navigation_memory.p.locationGraph.visuFrequency = 2
+# ArmarX.navigation_memory.p.locationGraph.visuFrequency = 10
 
 
 # ArmarX.navigation_memory.p.locationGraph.visuGraphEdges:  Enable visualization of navigation graph edges.
diff --git a/source/armarx/navigation/components/human_simulator/CMakeLists.txt b/source/armarx/navigation/components/human_simulator/CMakeLists.txt
index 3ea4392a9fd911109b7f85046edec9d1c4d9469c..c5cb14c6099a66e52447e5654af7aadbf138dc7d 100644
--- a/source/armarx/navigation/components/human_simulator/CMakeLists.txt
+++ b/source/armarx/navigation/components/human_simulator/CMakeLists.txt
@@ -23,4 +23,7 @@ armarx_add_component(human_simulator
          armarx_navigation::dynamic_scene
          armarx_navigation::teb_human
          armarx_navigation::simulation
+
+        # HRVO::HRVO
+        RVO::RVO
 )
diff --git a/source/armarx/navigation/components/human_simulator/Component.cpp b/source/armarx/navigation/components/human_simulator/Component.cpp
index 3410013c006ce7d0ce85ed3a21629ff5f7430713..6ce73503ea0d6f7951fb70454ca19a89e6072bb8 100644
--- a/source/armarx/navigation/components/human_simulator/Component.cpp
+++ b/source/armarx/navigation/components/human_simulator/Component.cpp
@@ -23,17 +23,28 @@
 
 #include "Component.h"
 
+#include <cstddef>
 #include <cstdlib>
 
+#include <SimoxUtility/color/Color.h>
+#include <VirtualRobot/CollisionDetection/CollisionModel.h>
 #include <VirtualRobot/Random.h>
+#include <VirtualRobot/SceneObjectSet.h>
 
 #include "ArmarXCore/core/logging/Logging.h"
 #include <ArmarXCore/libraries/DecoupledSingleComponent/Decoupled.h>
 
+#include "RobotAPI/components/ArViz/Client/Elements.h"
+#include "RobotAPI/components/ArViz/Client/elements/Path.h"
+#include "RobotAPI/libraries/ArmarXObjects/plugins/ObjectPoseClientPlugin.h"
+
 #include "armarx/navigation/algorithms/Costmap.h"
 #include "armarx/navigation/core/basic_types.h"
 #include "armarx/navigation/human/types.h"
 #include "armarx/navigation/simulation/SimulatedHuman.h"
+#include "armarx/navigation/util/util.h"
+#include <RVOSimulator.h>
+#include <Vector2.h>
 
 // Include headers you only need in function definitions in the .cpp.
 
@@ -77,8 +88,9 @@ namespace armarx::navigation::components::human_simulator
         // Add an optionalproperty.
         def->optional(properties.taskPeriodMs, "p.taskPeriodMs", "");
         def->optional(properties.nHumans, "p.nHumans", "Number of humans to spawn.");
-        
-        def->optional(properties.humanParams.goalDistanceThreshold, "p.human.goalDistanceThreshold", "");
+
+        def->optional(
+            properties.humanParams.goalDistanceThreshold, "p.human.goalDistanceThreshold", "");
         def->optional(properties.humanParams.minLinearVelocity, "p.human.maxLinearVelocity", "");
         def->optional(properties.humanParams.maxLinearVelocity, "p.human.maxLinearVelocity", "");
 
@@ -96,40 +108,59 @@ namespace armarx::navigation::components::human_simulator
         // setDebugObserverBatchModeEnabled(true);
     }
 
-
     void
-    Component::onConnectComponent()
+    Component::setPreferredVelocities(RVO::RVOSimulator* simulator,
+                                      const std::vector<RVO::Vector2>& goals)
     {
-        // Do things after connecting to topics and components.
+        /* Set the preferred velocity to be a vector of unit magnitude (speed) in the
+   * direction of the goal. */
+        // #ifdef _OPENMP
+        // #pragma omp parallel for
+        // #endif /* _OPENMP */
 
-        /* (Requies the armarx::DebugObserverComponentPluginUser.)
-        // Use the debug observer to log data over time.
-        // The data can be viewed in the ObserverView and the LivePlotter.
-        // (Before starting any threads, we don't need to lock mutexes.)
+        for (int i = 0; i < static_cast<int>(properties.nHumans); ++i)
         {
-            setDebugObserverDatafield("numBoxes", properties.numBoxes);
-            setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
-            sendDebugObserverBatch();
-        }
-        */
+            // RVO::Vector2 goalVector = goals[i] - simulator->getAgentPosition(i);
 
-        /* (Requires the armarx::ArVizComponentPluginUser.)
-        // Draw boxes in ArViz.
-        // (Before starting any threads, we don't need to lock mutexes.)
-        drawBoxes(properties, arviz);
-        */
+            // if (RVO::absSq(goalVector) > 1.0F)
+            // {
+            //     goalVector = RVO::normalize(goalVector);
+            // }
 
-        /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
-        // Setup the remote GUI.
-        {
-            createRemoteGuiTab();
-            RemoteGui_startRunningTask();
-        }
-        */
+            const auto agentPosition = simulator->getAgentPosition(i);
+            auto& simulatedHuman = simulatedHumans.at(i);
+
+            core::Pose2D pose = core::Pose2D::Identity();
+            pose.translation().x() = agentPosition.x() * 1000; // [m] -> [mm]
+            pose.translation().y() = agentPosition.y() * 1000; // [m] -> [mm]
+
+            simulatedHuman.reinitialize(pose);
+
+            const std::vector<core::Position> trajectoryPoints =
+                simulatedHuman.trajectory().positions();
+
+            const std::size_t lookAheadGoalIdx = std::min(trajectoryPoints.size() - 1, 5ul);
+            const auto& intermediateGoal = trajectoryPoints.at(lookAheadGoalIdx);
 
+            const Eigen::Vector2f rvoGoalHelper = intermediateGoal.head<2>() / 1000; // [mm] -> [m]
 
-        ///
+            const RVO::Vector2 rvoGoal(rvoGoalHelper.x(), rvoGoalHelper.y());
 
+            RVO::Vector2 goalVector = rvoGoal - agentPosition;
+
+            if (RVO::absSq(goalVector) > 1.0F)
+            {
+                goalVector = RVO::normalize(goalVector);
+            }
+
+            simulator->setAgentPrefVelocity(i, goalVector);
+        }
+    }
+
+
+    void
+    Component::onConnectComponent()
+    {
         //
         //  Costmaps
         //
@@ -166,18 +197,120 @@ namespace armarx::navigation::components::human_simulator
             };
         }();
 
-        /// create humans
+        /// create simulation environment
+        {
+            ARMARX_INFO << "Creating sim";
 
-        simulatedHumans.clear();
+            simulator.setTimeStep(static_cast<float>(properties.taskPeriodMs) / 1000);
+            simulator.setAgentDefaults(15.0F, 10U, 1.5F, .1F, .4F, .5F);
 
-        for (std::size_t i = 0; i < properties.nHumans; i++)
-        {
-            simulatedHumans.emplace_back(costmap);
+            const objpose::ObjectPoseSeq obstacles =
+                ObjectPoseClientPluginUser::getObjectPosesByProvider(
+                    "R003_grasping_challenge_robot_placement_with_ivt_obstacles");
+
+            const auto objects = armarx::navigation::util::asSceneObjects(obstacles);
+
+
+            ARMARX_VERBOSE << obstacles.size() << " obstacles";
+
+            {
+                auto layer = arviz.layer("obstacles");
+
+
+                for (const auto& obst : objects->getCollisionModels())
+                {
+
+                    ARMARX_INFO << "adding obstacle ...";
+                    const VirtualRobot::BoundingBox bbox = obst->getGlobalBoundingBox();
+
+                    Eigen::Vector2f bbMin = bbox.getMin().head<2>();
+                    Eigen::Vector2f bbMax = bbox.getMax().head<2>();
+
+                    // add some margin to the obstacles
+                    const float margin = 100; // [mm]
+
+                    bbMin.x() -= margin;
+                    bbMin.y() -= margin;
+                    bbMax.x() += margin;
+                    bbMax.y() += margin;
+
+                    ARMARX_VERBOSE << "Bounding box: (" << bbMin.transpose() << "), ("
+                                   << bbMax.transpose() << ")";
+
+                    {
+                        constexpr float zHeight = 3; // [mm]
+
+                        viz::Polygon polygon(std::to_string(layer.size()));
+                        polygon.addPoint(Eigen::Vector3f{bbMin.x(), bbMin.y(), zHeight});
+                        polygon.addPoint(Eigen::Vector3f{bbMax.x(), bbMin.y(), zHeight});
+                        polygon.addPoint(Eigen::Vector3f{bbMax.x(), bbMax.y(), zHeight});
+                        polygon.addPoint(Eigen::Vector3f{bbMin.x(), bbMax.y(), zHeight});
+
+                        polygon.color(simox::Color::black());
+                        polygon.color(simox::Color::black());
+
+                        layer.add(polygon);
+                    }
+
+
+                    const Eigen::Vector2d min = bbMin.cast<double>() / 1000; // [mm] -> [m]
+                    const Eigen::Vector2d max = bbMax.cast<double>() / 1000; // [mm] -> [m]
+
+                    std::vector<RVO::Vector2> obstacle;
+                    obstacle.emplace_back(min.x(), min.y());
+                    obstacle.emplace_back(max.x(), min.y());
+                    obstacle.emplace_back(max.x(), max.y());
+                    obstacle.emplace_back(min.x(), max.y());
+
+                    simulator.addObstacle(obstacle);
+                }
+
+                arviz.commit(layer);
+            }
+
+            simulator.processObstacles();
         }
 
+        /// create humans in simulation
+        {
+            simulatedHumans.clear();
+
+            for (std::size_t i = 0U; i < properties.nHumans; ++i)
+            {
+                armarx::navigation::human::simulation::SimulatedHuman& human =
+                    simulatedHumans.emplace_back(costmap);
 
-        ///
+                const RVO::Vector2 position =
+                    RVO::Vector2(human.human().pose.translation().x() / 1000,
+                                 human.human().pose.translation().y() / 1000);
+                auto goal = human.trajectory().positions().back() / 1000; // [mm] -> [m]
 
+                ARMARX_VERBOSE << "Adding agent";
+                // simulator.addAgent(position, simulator.addGoal(hrvo::Vector2(goal.x(), goal.y())));
+                simulator.addAgent(
+                    position); // , simulator.addGoal(hrvo::Vector2(goal.x(), goal.y())));
+
+                goals.emplace_back(goal.x(), goal.y());
+            }
+        }
+
+        /// load robot and add it to the simulator
+        {
+            robot = virtualRobotReaderPlugin->get().getRobot(properties.robotName);
+            ARMARX_CHECK(
+                virtualRobotReaderPlugin->get().synchronizeRobot(*robot, armarx::Clock::Now()));
+
+            const auto robotPosH = robot->getGlobalPosition();
+            const RVO::Vector2 robotPos(robotPosH.x() / 1000, robotPosH.y() / 1000);
+
+            robotAgentId = simulator.addAgent(robotPos);
+            simulator.setAgentMaxSpeed(robotAgentId,
+                                       0); // we do not allow the robot to be perturbed
+            simulator.setAgentPrefVelocity(robotAgentId, RVO::Vector2(0, 0));
+            simulator.setAgentRadius(robotAgentId, 0.6);
+        }
+
+        /// start task
         task = new PeriodicTask<Component>(
             this, &Component::runPeriodically, properties.taskPeriodMs, false, "runningTask");
         task->start();
@@ -213,25 +346,58 @@ namespace armarx::navigation::components::human_simulator
     void
     Component::runPeriodically()
     {
-        // obtain data from perception
-
         const DateTime timestamp = Clock::Now();
 
-        //
-        // Robot
-        //
+        setPreferredVelocities(&simulator, goals);
 
-        // ARMARX_CHECK(virtualRobotReaderPlugin->get().synchronizeRobot(*robot, timestamp));
-        // const core::Pose global_T_robot(robot->getGlobalPose());
+        // TODO(fabian.reister): check how much the agents interact => this can be an evaluation criterion
 
-        // ARMARX_INFO << "Robot position: " << global_T_robot.translation().head<2>();
+        // update robot
+        {
+            ARMARX_CHECK(
+                virtualRobotReaderPlugin->get().synchronizeRobot(*robot, armarx::Clock::Now()));
 
+            const auto robotPosH = robot->getGlobalPosition();
+            const RVO::Vector2 robotPos(robotPosH.x() / 1000, robotPosH.y() / 1000);
 
-        human::Humans humans;
+            simulator.setAgentPosition(robotAgentId, robotPos);
+        }
+
+        simulator.doStep();
+
+        // visualize paths
+        {
+            auto layer = arviz.layer("trajectories");
+            for (const auto& simulatedHuman : simulatedHumans)
+            {
+                viz::Path path(std::to_string(layer.size()));
+
+                for (const auto& pt : simulatedHuman.trajectory().points())
+                {
+                    path.addPoint(pt.waypoint.pose.translation());
+                }
 
-        for (auto& simulatedHuman : simulatedHumans)
+                // unique and distinct color for this human
+                path.colorGlasbeyLUT(layer.size());
+
+                layer.add(path);
+            }
+
+            arviz.commit(layer);
+        }
+
+
+        human::Humans humans;
+        for (std::size_t i = 0; i < properties.nHumans; i++)
         {
-            humans.push_back(simulatedHuman.update());
+            const auto pos = simulator.getAgentPosition(i);
+
+            human::Human human;
+            human.pose.setIdentity();
+            human.pose.translation().x() = pos.x() * 1000; // [m] -> [mm]
+            human.pose.translation().y() = pos.y() * 1000; // [m] -> [mm]
+
+            humans.push_back(human);
         }
 
         ARMARX_VERBOSE << "Updating humans.";
diff --git a/source/armarx/navigation/components/human_simulator/Component.h b/source/armarx/navigation/components/human_simulator/Component.h
index 52e7aadfee802ea9034d0f50d14195782118345e..7235893d36fcd1661a82bb63123f60e85ccd2d9e 100644
--- a/source/armarx/navigation/components/human_simulator/Component.h
+++ b/source/armarx/navigation/components/human_simulator/Component.h
@@ -26,33 +26,38 @@
 
 // #include <mutex>
 
+#include <string>
+#include <VirtualRobot/VirtualRobot.h>
 #include "ArmarXCore/core/services/tasks/PeriodicTask.h"
 #include <ArmarXCore/core/Component.h>
-#include "RobotAPI/libraries/armem/client/plugins/ReaderWriterPlugin.h"
 
+#include "RobotAPI/libraries/ArmarXObjects/plugins/ObjectPoseClientPlugin.h"
+#include "RobotAPI/libraries/armem/client/plugins/ReaderWriterPlugin.h"
 #include "RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.h"
 
 // #include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
 
 // #include <ArmarXGui/libraries/ArmarXGuiComponentPlugins/LightweightRemoteGuiComponentPlugin.h>
 
-// #include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
 
-#include "armarx/navigation/simulation/SimulatedHuman.h"
 #include "armarx/navigation/memory/client/costmap/Reader.h"
 #include "armarx/navigation/memory/client/human/Writer.h"
+#include "armarx/navigation/simulation/SimulatedHuman.h"
+// #include <Simulator.h>
+#include "RVO.h"
 #include <armarx/navigation/components/human_simulator/ComponentInterface.h>
 
-
 namespace armarx::navigation::components::human_simulator
 {
 
     class Component :
         virtual public armarx::Component,
-        virtual public armarx::navigation::components::human_simulator::ComponentInterface
-    // , virtual public armarx::DebugObserverComponentPluginUser
-    // , virtual public armarx::LightweightRemoteGuiComponentPluginUser
-    // , virtual public armarx::ArVizComponentPluginUser
+        virtual public armarx::navigation::components::human_simulator::ComponentInterface,
+        virtual public armarx::ObjectPoseClientPluginUser,
+        // , virtual public armarx::DebugObserverComponentPluginUser
+        // , virtual public armarx::LightweightRemoteGuiComponentPluginUser
+        virtual public armarx::ArVizComponentPluginUser
     {
     public:
         Component();
@@ -106,6 +111,8 @@ namespace armarx::navigation::components::human_simulator
 
         void runPeriodically();
 
+        void setPreferredVelocities(RVO::RVOSimulator* simulator,
+                                    const std::vector<RVO::Vector2>& goals);
 
 
     private:
@@ -114,7 +121,6 @@ namespace armarx::navigation::components::human_simulator
         PeriodicTask<Component>::pointer_type task;
 
 
-
         // Private member variables go here.
 
 
@@ -127,6 +133,8 @@ namespace armarx::navigation::components::human_simulator
             std::size_t nHumans = 4;
 
             human::simulation::SimulatedHumanParams humanParams;
+
+            std::string robotName = "Armar6";
         };
         Properties properties;
         /* Use a mutex if you access variables from different threads
@@ -157,6 +165,9 @@ namespace armarx::navigation::components::human_simulator
         template <typename T>
         using ReaderWriterPlugin = armem::client::plugins::ReaderWriterPlugin<T>;
 
+        VirtualRobot::RobotPtr robot;
+
+        std::size_t robotAgentId;
 
         ReaderWriterPlugin<armem::robot_state::VirtualRobotReader>* virtualRobotReaderPlugin =
             nullptr;
@@ -166,10 +177,13 @@ namespace armarx::navigation::components::human_simulator
 
         ReaderWriterPlugin<memory::client::human::Writer>* humanWriterPlugin = nullptr;
 
-    
+
         std::vector<human::simulation::SimulatedHuman> simulatedHumans;
 
+        // hrvo::Simulator simulator;
+        RVO::RVOSimulator simulator;
 
+        std::vector<RVO::Vector2> goals;
     };
 
 } // namespace armarx::navigation::components::human_simulator
diff --git a/source/armarx/navigation/simulation/SimulatedHuman.cpp b/source/armarx/navigation/simulation/SimulatedHuman.cpp
index 0a4d735dff8efc31ca6e49c987568af159139b24..857ad24282a527fc40fe436a9c1a7703a41d7c04 100644
--- a/source/armarx/navigation/simulation/SimulatedHuman.cpp
+++ b/source/armarx/navigation/simulation/SimulatedHuman.cpp
@@ -29,6 +29,7 @@
 #include "armarx/navigation/algorithms/util.h"
 #include "armarx/navigation/conversions/eigen.h"
 #include "armarx/navigation/core/StaticScene.h"
+#include "armarx/navigation/core/basic_types.h"
 #include "armarx/navigation/core/types.h"
 #include "armarx/navigation/global_planning/SPFA.h"
 #include "armarx/navigation/human/types.h"
@@ -53,10 +54,7 @@ namespace armarx::navigation::human::simulation
 
                 step();
 
-                const Eigen::Vector2f goal =
-                    conv::to2D(globalTrajectory_.points().back().waypoint.pose.translation());
-
-                if ((goal - human_.pose.translation()).norm() < params_.goalDistanceThreshold)
+                if (goalReached())
                 {
                     ARMARX_INFO << "Human reached goal";
                     state_ = State::GoalReached;
@@ -75,6 +73,31 @@ namespace armarx::navigation::human::simulation
         return human_;
     }
 
+    bool
+    SimulatedHuman::goalReached() const
+    {
+        const Eigen::Vector2f goal =
+            conv::to2D(globalTrajectory_.points().back().waypoint.pose.translation());
+
+        return ((goal - human_.pose.translation()).norm() < params_.goalDistanceThreshold);
+    }
+
+    void
+    SimulatedHuman::reinitialize(const core::Pose2D& pose)
+    {
+        human_.pose = pose;
+
+        if(goalReached())
+        {
+            ARMARX_VERBOSE << "Goal reached";
+            state_ = State::Idle;
+        }
+
+        initialize();
+        update();
+
+    }
+
     void
     SimulatedHuman::initialize()
     {
@@ -88,14 +111,34 @@ namespace armarx::navigation::human::simulation
 
         global_planning::SPFA planner(params, scene);
 
-        const auto start = human_.pose;
+        const core::Pose2D start = human_.pose;
 
-        while (true)
+        if (state_ == State::Idle) // human reached goal and needs a new one
         {
-            const auto sampledPose = algorithms::sampleValidPositionInMap(distanceField_);
-            ARMARX_CHECK(sampledPose.has_value());
-            const auto& goal = sampledPose.value();
+            while (true)
+            {
+                const auto sampledPose = algorithms::sampleValidPositionInMap(distanceField_);
+                ARMARX_CHECK(sampledPose.has_value());
+                const core::Pose2D& goal = sampledPose.value();
+
+
+                const auto plan = planner.plan(conv::to3D(start), conv::to3D(goal));
+
+                // check if plan could be created. otherwise try another goal
+                if (plan.has_value())
+                {
+                    globalTrajectory_ = plan->trajectory;
 
+                    human_ = human::Human{.pose = start,
+                                          .linearVelocity = Eigen::Vector2f::Zero(),
+                                          .detectionTime = Clock::Now()};
+                    return;
+                }
+            }
+        }
+        else if (state_ == State::Walking) // human is walking and replans to existing goal
+        {
+            const auto goal = conv::to2D(globalTrajectory_.poses().back());
             const auto plan = planner.plan(conv::to3D(start), conv::to3D(goal));
 
             // check if plan could be created. otherwise try another goal
@@ -148,5 +191,7 @@ namespace armarx::navigation::human::simulation
         const auto sampledPose = algorithms::sampleValidPositionInMap(distanceField_);
         ARMARX_CHECK(sampledPose.has_value());
         human_.pose = sampledPose.value();
+
+        update(); // should bring the robot into walking state
     }
 } // namespace armarx::navigation::human::simulation
diff --git a/source/armarx/navigation/simulation/SimulatedHuman.h b/source/armarx/navigation/simulation/SimulatedHuman.h
index fa4ed6a8a01a748937c8aa4a57b5f9185705cbe7..b1bdc55658c24755f6094b45cdbd40e9ac017f18 100644
--- a/source/armarx/navigation/simulation/SimulatedHuman.h
+++ b/source/armarx/navigation/simulation/SimulatedHuman.h
@@ -31,10 +31,10 @@ namespace armarx::navigation::human::simulation
 
     struct SimulatedHumanParams
     {
-        float goalDistanceThreshold = 100;
+        float goalDistanceThreshold = 100; // [mm]
 
-        float minLinearVelocity = 100;
-        float maxLinearVelocity = 200;
+        float minLinearVelocity = 100; // [mm/s]
+        float maxLinearVelocity = 200; // [mm/s]
     };
 
     class SimulatedHuman
@@ -46,6 +46,34 @@ namespace armarx::navigation::human::simulation
 
         Human update();
 
+
+        human::Human&
+        human()
+        {
+            return human_;
+        }
+
+        core::GlobalTrajectory&
+        trajectory()
+        {
+            return globalTrajectory_;
+        }
+
+        const core::GlobalTrajectory&
+        trajectory() const
+        {
+            return globalTrajectory_;
+        }
+
+        bool goalReached() const;
+
+        /**
+         * @brief resets the human to the given pose and replans the global optimal trajectory
+         * 
+         * @param pose 
+         */
+        void reinitialize(const core::Pose2D& pose);
+
     protected:
         void initialize();
 
@@ -58,6 +86,7 @@ namespace armarx::navigation::human::simulation
             GoalReached
         };
 
+
     private:
         const algorithms::Costmap distanceField_;