diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
index 3cb09a7b0359bf73b5b577c48bf5545573c20b21..73305adb72fd432d59959e3a6c4f19b3b35d8e6a 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
+++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
@@ -679,21 +679,25 @@ namespace armarx
         CycleUtil cycle(static_cast<int>(1000 / visu.frequencyHz));
         while (visu.updateTask && !visu.updateTask->isStopped())
         {
-            TIMING_START(Visu);
-            if (visu.enabled)
             {
-                std::scoped_lock lock(dataMutex);
-                visualizeCommit(data.objectPoses, data.robot);
-            }
-            if (visu.enabled)
-            {
-                TIMING_END_STREAM(Visu, ARMARX_VERBOSE);
-                if (debugObserver)
+                std::scoped_lock lock(visuMutex);
+
+                TIMING_START(Visu);
+                if (visu.enabled)
+                {
+                    std::scoped_lock lock(dataMutex);
+                    visualizeCommit(data.objectPoses, data.robot);
+                }
+                if (visu.enabled)
                 {
-                    debugObserver->setDebugChannel(getName(),
+                    TIMING_END_STREAM(Visu, ARMARX_VERBOSE);
+                    if (debugObserver)
                     {
-                        { "Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) },
-                    });
+                        debugObserver->setDebugChannel(getName(),
+                        {
+                            { "Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) },
+                        });
+                    }
                 }
             }
             cycle.waitForCycleDuration();
@@ -813,28 +817,32 @@ namespace armarx
         CycleUtil cycle(static_cast<int>(1000 / decay.updateFrequencyHz));
         while (decay.updateTask && !decay.updateTask->isStopped())
         {
-            TIMING_START(Decay);
-            if (decay.enabled)
             {
-                std::scoped_lock lock(dataMutex);
-                IceUtil::Time now = TimeUtil::GetTime();
-                for (auto& [providerName, objectPoses] : data.objectPoses)
+                std::scoped_lock lock(decayMutex);
+
+                TIMING_START(Decay);
+                if (decay.enabled)
                 {
-                    for (objpose::ObjectPose& pose : objectPoses)
+                    std::scoped_lock lock(dataMutex);
+                    IceUtil::Time now = TimeUtil::GetTime();
+                    for (auto& [providerName, objectPoses] : data.objectPoses)
                     {
-                        decay.updateConfidence(pose, now);
+                        for (objpose::ObjectPose& pose : objectPoses)
+                        {
+                            decay.updateConfidence(pose, now);
+                        }
                     }
                 }
-            }
-            if (decay.enabled)
-            {
-                TIMING_END_STREAM(Decay, ARMARX_VERBOSE);
-                if (debugObserver)
+                if (decay.enabled)
                 {
-                    debugObserver->setDebugChannel(getName(),
+                    TIMING_END_STREAM(Decay, ARMARX_VERBOSE);
+                    if (debugObserver)
                     {
-                        { "Decay Update [ms]", new Variant(Decay.toMilliSecondsDouble()) },
-                    });
+                        debugObserver->setDebugChannel(getName(),
+                        {
+                            { "Decay Update [ms]", new Variant(Decay.toMilliSecondsDouble()) },
+                        });
+                    }
                 }
             }
 
@@ -973,7 +981,52 @@ namespace armarx
             robotHeadGroup.addChild(grid);
         }
 
-        VBoxLayout root = {visuGroup, robotHeadGroup, VSpacer()};
+        GroupBox decayGroup;
+        {
+            tab.decay.enabled.setValue(decay.enabled);
+            {
+                float max = 1e6;
+                tab.decay.delaySeconds.setRange(0, max);
+                tab.decay.delaySeconds.setDecimals(2);
+                tab.decay.delaySeconds.setSteps(int(10 * max));  // = 0.1 steps
+                tab.decay.delaySeconds.setValue(decay.delaySeconds);
+            }
+            {
+                float max = 1e6;
+                tab.decay.durationSeconds.setRange(0, max);
+                tab.decay.durationSeconds.setDecimals(2);
+                tab.decay.durationSeconds.setSteps(int(10 * max));  // = 0.1 steps
+                tab.decay.durationSeconds.setValue(decay.durationSeconds);
+            }
+            {
+                tab.decay.maxConfidence.setRange(0, 1);
+                tab.decay.maxConfidence.setSteps(20);
+                tab.decay.maxConfidence.setValue(decay.maxConfidence);
+            }
+            {
+                tab.decay.minConfidence.setRange(0, 1);
+                tab.decay.minConfidence.setSteps(20);
+                tab.decay.minConfidence.setValue(decay.minConfidence);
+            }
+
+            GridLayout grid;
+            int row = 0;
+            grid.add(Label("Enabled"), {row, 0}).add(tab.decay.enabled, {row, 1});
+            row++;
+            grid.add(Label("Delay [sec]"), {row, 0}).add(tab.decay.delaySeconds, {row, 1});
+            row++;
+            grid.add(Label("Duration [sec]"), {row, 0}).add(tab.decay.durationSeconds, {row, 1});
+            row++;
+            grid.add(Label("Max Confidence"), {row, 0}).add(tab.decay.maxConfidence, {row, 1});
+            row++;
+            grid.add(Label("Min Confidence"), {row, 0}).add(tab.decay.minConfidence, {row, 1});
+            row++;
+
+            decayGroup.setLabel("Decay");
+            decayGroup.addChild(grid);
+        }
+
+        VBoxLayout root = {visuGroup, decayGroup, robotHeadGroup, VSpacer()};
         RemoteGui_createTab(getName(), root, &tab);
     }
 
@@ -981,7 +1034,7 @@ namespace armarx
     {
         // Non-atomic variables need to be guarded by a mutex if accessed by multiple threads
         {
-            std::scoped_lock lock(dataMutex);
+            std::scoped_lock lock(visuMutex);
 
             visu.enabled = tab.visu.enabled.getValue();
             visu.inGlobalFrame = tab.visu.inGlobalFrame.getValue();
@@ -992,10 +1045,20 @@ namespace armarx
         }
         {
             std::scoped_lock lock(robotHeadMutex);
+
             robotHead.checkHeadVelocity = tab.robotHead.checkHeadVelocity.getValue();
             robotHead.maxJointVelocity = tab.robotHead.maxJointVelocity.getValue();
             robotHead.discardIntervalAfterMoveMS = tab.robotHead.discardIntervalAfterMoveMS.getValue();
         }
+        {
+            std::scoped_lock lock(decayMutex);
+
+            decay.enabled = tab.decay.enabled.getValue();
+            decay.delaySeconds = tab.decay.delaySeconds.getValue();
+            decay.durationSeconds = tab.decay.durationSeconds.getValue();
+            decay.maxConfidence = tab.decay.maxConfidence.getValue();
+            decay.minConfidence = tab.decay.minConfidence.getValue();
+        }
     }
 
     void ObjectPoseObserver::Visu::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix)
diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
index 1c4f032ff7e52c8ac1e770c77cbbf4ec8103a4f5..cb42484ce3f18ffb709b98fd066a8499f0f7dc06 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
+++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
@@ -192,11 +192,12 @@ namespace armarx
 
             bool isAttachedCached(objpose::ObjectPose& objectPose) const;
         };
-        std::mutex dataMutex;
         Data data;
+        std::mutex dataMutex;
 
 
         objpose::ObjectPoseDecay decay;
+        std::mutex decayMutex;
 
 
         objpose::RobotHeadMovement robotHead;
@@ -220,6 +221,7 @@ namespace armarx
             void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu.");
         };
         Visu visu;
+        std::mutex visuMutex;
 
         struct Calibration
         {
@@ -236,6 +238,7 @@ namespace armarx
             struct Visu
             {
                 RemoteGui::Client::CheckBox enabled;
+
                 RemoteGui::Client::CheckBox inGlobalFrame;
                 RemoteGui::Client::FloatSlider alpha;
                 RemoteGui::Client::CheckBox alphaByConfidence;
@@ -252,6 +255,17 @@ namespace armarx
                 RemoteGui::Client::IntSpinBox discardIntervalAfterMoveMS;
             };
             RobotHead robotHead;
+
+            struct Decay
+            {
+                RemoteGui::Client::CheckBox enabled;
+
+                RemoteGui::Client::FloatSpinBox delaySeconds;
+                RemoteGui::Client::FloatSpinBox durationSeconds;
+                RemoteGui::Client::FloatSlider maxConfidence;
+                RemoteGui::Client::FloatSlider minConfidence;
+            };
+            Decay decay;
         };
         RemoteGuiTab tab;
 
diff --git a/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.cpp b/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.cpp
index e7406a5e30ad69ee6c421b38ec66b30bc72c53f2..234374a3c4dda96fd559e30f06e8aadc6334fb50 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.cpp
+++ b/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.cpp
@@ -12,7 +12,7 @@ namespace armarx::objpose
     {
         defs->optional(enabled, prefix + "enabled",
                        "If true, object poses decay over time when not localized anymore.");
-        defs->optional(noDecaySeconds, prefix + "noDecaySeconds",
+        defs->optional(delaySeconds, prefix + "delaySeconds",
                        "Duration after latest localization before decay starts.");
         defs->optional(durationSeconds, prefix + "durationSeconds",
                        "How long to reach minimal confidence.");
@@ -31,11 +31,11 @@ namespace armarx::objpose
     float ObjectPoseDecay::calculateConfidence(IceUtil::Time localization, IceUtil::Time now)
     {
         float duration = (now - localization).toSeconds();
-        if (duration < noDecaySeconds)
+        if (duration < delaySeconds)
         {
             return maxConfidence;
         }
-        else if (duration > noDecaySeconds + this->durationSeconds)
+        else if (duration > delaySeconds + this->durationSeconds)
         {
             return minConfidence;
         }
@@ -43,7 +43,7 @@ namespace armarx::objpose
         {
             return simox::math::scale_value_from_to(
                        duration,
-                       noDecaySeconds, noDecaySeconds + this->durationSeconds,
+                       delaySeconds, delaySeconds + this->durationSeconds,
                        maxConfidence, minConfidence);
         }
     }
diff --git a/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.h b/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.h
index b55824a7cbfbf230d80a55dac74b924ba595106c..a66d9977097a354ca7eae420bce450296db925ab 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.h
+++ b/source/RobotAPI/components/ObjectPoseObserver/detail/ObjectPoseDecay.h
@@ -33,7 +33,7 @@ namespace armarx::objpose
         bool enabled = false;
 
         /// Duration after latest localization before decay starts.
-        float noDecaySeconds = 5.0;
+        float delaySeconds = 5.0;
         /// How long to reach minConfidence.
         float durationSeconds = 20.0;