From f33d0017ff2e395430eac6017f31b9c034ca3eb8 Mon Sep 17 00:00:00 2001
From: Fabian Peller-Konrad <fabian.peller-konrad@kit.edu>
Date: Fri, 12 Aug 2022 10:41:34 +0200
Subject: [PATCH] added mutexes to memory viewer to avoid data races. Removed
 data race of removed address in asynch method

---
 .../libraries/armem/client/Reader.cpp         |   2 +
 .../RobotAPI/libraries/armem/client/Reader.h  |   2 +-
 .../armem/server/MemoryToIceAdapter.cpp       |   1 -
 .../libraries/armem_gui/MemoryViewer.cpp      |  94 ++++---
 .../libraries/armem_gui/MemoryViewer.h        |  17 +-
 .../armem_gui/query_widgets/QueryWidget.cpp   |   8 +-
 .../armem_gui/query_widgets/QueryWidget.h     |   4 +
 source/RobotAPI/libraries/core/FramedPose.cpp | 233 ++++++++++++++----
 source/RobotAPI/libraries/core/FramedPose.h   |  29 ++-
 9 files changed, 289 insertions(+), 101 deletions(-)

diff --git a/source/RobotAPI/libraries/armem/client/Reader.cpp b/source/RobotAPI/libraries/armem/client/Reader.cpp
index 872f4b7dd..48efb7bb9 100644
--- a/source/RobotAPI/libraries/armem/client/Reader.cpp
+++ b/source/RobotAPI/libraries/armem/client/Reader.cpp
@@ -16,6 +16,7 @@
 #include "query/Builder.h"
 #include "query/query_fns.h"
 
+#include <mutex>
 
 namespace armarx::armem::client
 {
@@ -46,6 +47,7 @@ namespace armarx::armem::client
 
         try
         {
+            ARMARX_TRACE;
             result = readingPrx->query(input);
         }
         catch (const Ice::LocalException& e)
diff --git a/source/RobotAPI/libraries/armem/client/Reader.h b/source/RobotAPI/libraries/armem/client/Reader.h
index 8f78b33ec..875250eb8 100644
--- a/source/RobotAPI/libraries/armem/client/Reader.h
+++ b/source/RobotAPI/libraries/armem/client/Reader.h
@@ -4,6 +4,7 @@
 // STD/STL
 #include <optional>
 #include <vector>
+#include <mutex>
 
 // RobotAPI
 #include <RobotAPI/interface/armem/server/ReadingMemoryInterface.h>
@@ -203,7 +204,6 @@ namespace armarx::armem::client
 
         server::ReadingMemoryInterfacePrx readingPrx;
         server::PredictingMemoryInterfacePrx predictionPrx;
-
     };
 
 } // namespace armarx::armem::client
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
index 93673c8aa..6aa17f4ce 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
@@ -279,7 +279,6 @@ namespace armarx::armem::server
 
         if (not ltmResult.empty())
         {
-            ARMARX_INFO << "The LTM returned data after query";
 
             // convert memory ==> meaning resolving references
             // upon query, the LTM only returns a structure of the data (memory without data)
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
index be54e55ab..699a41d01 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
@@ -212,6 +212,7 @@ namespace armarx::armem::gui
             component.usingProxy(debugObserverName);
         }
 
+        is_initialized = true;
         emit initialized();
     }
 
@@ -234,8 +235,10 @@ namespace armarx::armem::gui
         {
             component.getProxy(debugObserver, debugObserverName, false, "", false);
         }
+
         updateWidget->startTimerIfEnabled();
 
+        is_connected = true;
         emit connected();
     }
 
@@ -243,6 +246,7 @@ namespace armarx::armem::gui
     void
     MemoryViewer::onDisconnect(ManagedIceObject&)
     {
+        periodicUpdateTimer->stop();
         updateWidget->stopTimer();
 
         emit disconnected();
@@ -252,6 +256,7 @@ namespace armarx::armem::gui
     const armem::wm::Memory*
     MemoryViewer::getSingleMemoryData(const std::string& memoryName)
     {
+        std::scoped_lock l(memoryDataMutex);
         auto it = memoryData.find(memoryName);
         if (it == memoryData.end())
         {
@@ -308,6 +313,8 @@ namespace armarx::armem::gui
     void
     MemoryViewer::startLTMRecording()
     {
+        std::scoped_lock l(memoryReaderMutex);
+
         TIMING_START(MemoryStartRecording);
 
         auto enabledMemories = memoryGroup->queryWidget()->enabledMemories();
@@ -327,6 +334,8 @@ namespace armarx::armem::gui
     void
     MemoryViewer::stopLTMRecording()
     {
+        std::scoped_lock l(memoryReaderMutex);
+
         TIMING_START(MemoryStopRecording);
 
         auto enabledMemories = memoryGroup->queryWidget()->enabledMemories();
@@ -345,6 +354,8 @@ namespace armarx::armem::gui
 
     void MemoryViewer::commit()
     {
+        std::scoped_lock l(memoryWriterMutex);
+
         TIMING_START(Commit);
         auto now = armem::Time::Now();
 
@@ -367,7 +378,6 @@ namespace armarx::armem::gui
             // ToDo: multiple objects
             auto aron = aron::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject(json);
 
-            memoryWriters = mns.getAllWriters(true);
             if (const auto& it = memoryWriters.find(memId.memoryName); it == memoryWriters.end())
             {
                 ARMARX_WARNING << "No memory with name '" << memId.memoryName << "' available for commit.";
@@ -391,6 +401,7 @@ namespace armarx::armem::gui
     void
     MemoryViewer::storeOnDisk(QString directory)
     {
+        std::scoped_lock l(memoryDataMutex);
         TIMING_START(MemoryExport)
 
         std::string status;
@@ -404,11 +415,12 @@ namespace armarx::armem::gui
     void
     MemoryViewer::loadFromDisk(QString directory)
     {
+        std::scoped_lock l(memoryWriterMutex);
+
         std::string status;
         std::map<std::string, wm::Memory> data =
             diskControl->loadFromDisk(directory, memoryGroup->queryInput(), &status);
 
-        memoryWriters = mns.getAllWriters(true);
         for (auto& [name, memory] : data)
         {
             if (memoryWriters.count(name) > 0)
@@ -431,16 +443,14 @@ namespace armarx::armem::gui
     void
     MemoryViewer::startQueries()
     {
-        memoryReaders = mns.getAllReaders(true);
-        startDueQueries(runningQueries, memoryReaders);
+        startDueQueries();
     }
 
 
     void
     MemoryViewer::processQueryResults()
     {
-        const std::map<std::string, client::QueryResult> results =
-            collectQueryResults(runningQueries, memoryReaders);
+        const std::map<std::string, client::QueryResult> results = collectQueryResults();
 
         int errorCount = 0;
         applyQueryResults(results, &errorCount);
@@ -469,17 +479,18 @@ namespace armarx::armem::gui
 
 
     void
-    MemoryViewer::startDueQueries(
-        std::map<std::string, std::future<armem::query::data::Result>>& queries,
-        const std::map<std::string, armem::client::Reader>& readers)
+    MemoryViewer::startDueQueries()
     {
+        std::scoped_lock l(memoryReaderMutex);
+        std::scoped_lock l2(runningQueriesMutex);
+
         armem::client::QueryInput input = memoryGroup->queryInput();
         int recursionDepth = memoryGroup->queryWidget()->queryLinkRecursionDepth();
 
         // Can't use a structured binding here because you can't capture those in a lambda
         // according to the C++ standard.
         auto enabledMemories = memoryGroup->queryWidget()->enabledMemories();
-        for (const auto& pair : readers)
+        for (const auto& pair : memoryReaders)
         {
             // skip if memory should not be queried
             if (std::find(enabledMemories.begin(), enabledMemories.end(), pair.first) == enabledMemories.end())
@@ -489,40 +500,44 @@ namespace armarx::armem::gui
 
             const auto& name = pair.first;
             const auto& reader = pair.second;
-            if (queries.count(name) == 0)
+
+            // skip if query already running
+            if (runningQueries.count(name) != 0)
             {
-                // You could pass the query function itself to async here,
-                // but that caused severe template headaches when I tried it.
-                queries[name] =
-                    std::async(std::launch::async,
-                               [&reader, input, recursionDepth, this]()
-                               {
-                                   // Can't resolve MemoryLinks without data
-                                   return recursionDepth == 0 || input.dataMode == armem::query::DataMode::NoData
-                                              ? reader.query(input.toIce())
-                                              : reader.query(input.toIce(), mns, recursionDepth);
-                               });
+                continue;
             }
+
+            // You could pass the query function itself to async here,
+            // but that caused severe template headaches when I tried it.
+            runningQueries[name] = std::async(std::launch::async,
+                   [reader, input, recursionDepth, this]()
+                   {
+                       // Can't resolve MemoryLinks without data
+                       return recursionDepth == 0 || input.dataMode == armem::query::DataMode::NoData
+                                  ? reader.query(input.toIce())
+                                  : reader.query(input.toIce(), mns, recursionDepth);
+                   });
         }
     }
 
 
     std::map<std::string, client::QueryResult>
-    MemoryViewer::collectQueryResults(
-        std::map<std::string, std::future<armem::query::data::Result>>& queries,
-        const std::map<std::string, client::Reader>& readers)
+    MemoryViewer::collectQueryResults()
     {
+        std::scoped_lock l(memoryReaderMutex);
+        std::scoped_lock l2(runningQueriesMutex);
+
         TIMING_START(tCollectQueryResults)
 
         std::map<std::string, client::QueryResult> results;
-        for (auto it = queries.begin(); it != queries.end();)
+        for (auto it = runningQueries.begin(); it != runningQueries.end();)
         {
             const std::string& name = it->first;
             std::future<armem::query::data::Result>* queryPromise = &it->second;
 
             if (queryPromise->wait_for(std::chrono::seconds(0)) == std::future_status::ready)
             {
-                if (auto jt = memoryReaders.find(name); jt != readers.end())
+                if (auto jt = memoryReaders.find(name); jt != memoryReaders.end())
                 {
                     try
                     {
@@ -536,7 +551,7 @@ namespace armarx::armem::gui
                 // else: Server is gone (MNS knew about it) => Skip result.
 
                 // Promise is completed => Clean up in any case.
-                it = queries.erase(it);
+                it = runningQueries.erase(it);
             }
             else
             {
@@ -561,9 +576,9 @@ namespace armarx::armem::gui
 
 
     void
-    MemoryViewer::applyQueryResults(const std::map<std::string, client::QueryResult>& results,
-                                    int* outErrorCount)
+    MemoryViewer::applyQueryResults(const std::map<std::string, client::QueryResult>& results, int* outErrorCount)
     {
+        std::scoped_lock l(memoryDataMutex);
         TIMING_START(tProcessQueryResults)
         for (const auto& [name, result] : results)
         {
@@ -573,8 +588,7 @@ namespace armarx::armem::gui
             }
             else
             {
-                ARMARX_WARNING << "Querying memory server '" << name << "' produced an error: \n"
-                               << result.errorMessage;
+                ARMARX_WARNING << "Querying memory server '" << name << "' produced an error: \n" << result.errorMessage;
                 if (outErrorCount)
                 {
                     outErrorCount++;
@@ -635,6 +649,7 @@ namespace armarx::armem::gui
     void
     MemoryViewer::updateInstanceTree(const armem::MemoryID& selectedID)
     {
+        std::scoped_lock l(memoryDataMutex);
         const armem::wm::Memory* data = getSingleMemoryData(selectedID.memoryName);
         if (data)
         {
@@ -686,6 +701,7 @@ namespace armarx::armem::gui
     void
     MemoryViewer::resolveMemoryID(const MemoryID& id)
     {
+        std::scoped_lock l(memoryDataMutex);
         // ARMARX_IMPORTANT << "Resolving memory ID: " << id;
 
         auto handleError = [this](const std::string& msg)
@@ -757,19 +773,24 @@ namespace armarx::armem::gui
     void
     MemoryViewer::updateAvailableMemories()
     {
-        if (mns) // mns must be initialized
+        std::scoped_lock l(memoryReaderMutex);
+        std::scoped_lock l2(memoryWriterMutex);
+
+        if (is_connected and mns) // mns must be connected and mns must be available
         {
             try
             {
+                memoryReaders = mns.getAllReaders(true);
+                memoryWriters = mns.getAllWriters(true);
+
                 std::vector<std::string> convVec;
-                memoryReaders = mns.getAllReaders(true); // we only need the readers
                 std::transform(memoryReaders.begin(), memoryReaders.end(), std::back_inserter(convVec), [](const auto& p){return p.first;});
 
                 TIMING_START(GuiUpdateAvailableMemories);
                 memoryGroup->queryWidget()->update(convVec);
                 TIMING_END_STREAM(GuiUpdateAvailableMemories, ARMARX_VERBOSE);
             }
-            catch (const std::exception& e)
+            catch (...)
             {
                 // MNS was killed/stopped
                 // ignore?!
@@ -785,6 +806,7 @@ namespace armarx::armem::gui
     void
     MemoryViewer::updateMemoryTree()
     {
+        std::scoped_lock l(memoryDataMutex);
         std::map<std::string, const armem::wm::Memory*> convMap;
         for (auto& [name, data] : memoryData)
         {
@@ -923,6 +945,8 @@ namespace armarx::armem::gui
                                  const armarx::DateTime& timestamp,
                                  const std::string& engineID)
     {
+        std::scoped_lock l(memoryReaderMutex);
+
         std::stringstream errorStream;
         auto showError = [this, &errorStream]()
         {
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
index 8cc41498c..f9ceb7471 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.h
@@ -129,14 +129,10 @@ namespace armarx::armem::gui
 
 
         /// Start a query for each entry in `memoryReaders` which is not in `runningQueries`.
-        void startDueQueries(
-            std::map<std::string, std::future<armem::query::data::Result>>& queries,
-            const std::map<std::string, armem::client::Reader>& readers);
+        void startDueQueries();
 
         std::map<std::string, client::QueryResult>
-        collectQueryResults(
-            std::map<std::string, std::future<armem::query::data::Result>>& queries,
-            const std::map<std::string, armem::client::Reader>& readers);
+        collectQueryResults();
 
         void applyQueryResults(
             const std::map<std::string, client::QueryResult>& results,
@@ -148,10 +144,15 @@ namespace armarx::armem::gui
         std::string mnsName;
         armem::client::MemoryNameSystem mns;
 
+        mutable std::recursive_mutex memoryReaderMutex;
+        mutable std::recursive_mutex memoryWriterMutex;
         std::map<std::string, armem::client::Reader> memoryReaders;
         std::map<std::string, armem::client::Writer> memoryWriters;
+
+        mutable std::recursive_mutex memoryDataMutex;
         std::map<std::string, armem::wm::Memory> memoryData;
 
+        mutable std::recursive_mutex runningQueriesMutex;
         std::map<std::string, std::future<armem::query::data::Result>> runningQueries;
 
         /// Periodically triggers query result collection and updates the available memories
@@ -177,6 +178,10 @@ namespace armarx::armem::gui
         // Queries.
         armem::query::data::EntityQueryPtr entityQuery;
 
+        // others
+        std::atomic_bool is_initialized = false;
+        std::atomic_bool is_connected = false;
+
     };
 
 }
diff --git a/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.cpp b/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.cpp
index 1719e6cac..54e5aaec3 100644
--- a/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.cpp
+++ b/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.cpp
@@ -103,11 +103,7 @@ namespace armarx::armem::gui
 
     void QueryWidget::update(const std::vector<std::string>& activeMemoryNames)
     {
-        // since this is the only method that adds or hides elements of the groupbox after initialization,
-        // we can use a static mutex, only available to this method
-        //static std::mutex m;
-
-        //std::scoped_lock l(m);
+        std::scoped_lock l(enabledMemoriesMutex);
         std::vector<std::string> alreadyPresentMemoryCheckboxes;
 
         // get information about memories already present and activate inactive ones if necessary
@@ -169,6 +165,8 @@ namespace armarx::armem::gui
 
     std::vector<std::string> QueryWidget::enabledMemories() const
     {
+        std::scoped_lock l(enabledMemoriesMutex);
+
         std::vector<std::string> enabledMemoryCheckboxes;
         int maxIndex = _availableMemoriesGroupBox->layout()->count();
         for (int i = 0; i < maxIndex; ++i)
diff --git a/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.h b/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.h
index bb285a9a4..d3d534e5b 100644
--- a/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.h
+++ b/source/RobotAPI/libraries/armem_gui/query_widgets/QueryWidget.h
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <mutex>
+
 #include <RobotAPI/libraries/armem/core/query/DataMode.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
 
@@ -68,6 +70,8 @@ namespace armarx::armem::gui
 
         QGroupBox* _additionalSettingsGroupBox;
         QGroupBox* _availableMemoriesGroupBox;
+
+        mutable std::mutex enabledMemoriesMutex;
     };
 
 }
diff --git a/source/RobotAPI/libraries/core/FramedPose.cpp b/source/RobotAPI/libraries/core/FramedPose.cpp
index e84ad2fc7..21049a274 100644
--- a/source/RobotAPI/libraries/core/FramedPose.cpp
+++ b/source/RobotAPI/libraries/core/FramedPose.cpp
@@ -84,15 +84,21 @@ namespace armarx
     }
 
     FramedDirectionPtr FramedDirection::ChangeFrame(const VirtualRobot::RobotPtr& robot, const FramedDirection& framedVec, const std::string& newFrame)
+    {
+        ARMARX_CHECK_NOT_NULL(robot);
+        return ChangeFrame(*robot, framedVec, newFrame);
+    }
+
+    FramedDirectionPtr FramedDirection::ChangeFrame(const VirtualRobot::Robot& robot, const FramedDirection& framedVec, const std::string& newFrame)
     {
         if (framedVec.getFrame() == newFrame)
         {
             return FramedDirectionPtr::dynamicCast(framedVec.clone());
         }
 
-        if (!robot->hasRobotNode(newFrame))
+        if (!robot.hasRobotNode(newFrame))
         {
-            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << robot->getName();
+            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << robot.getName();
         }
 
         Eigen::Matrix4f rotToNewFrame = __GetRotationBetweenFrames(framedVec.frame, newFrame, robot);
@@ -106,11 +112,17 @@ namespace armarx
         result->y = newVec(1);
         result->z = newVec(2);
         result->frame = newFrame;
-        result->agent = robot->getName();
+        result->agent = robot.getName();
         return result;
     }
 
     void FramedDirection::changeFrame(const VirtualRobot::RobotPtr& robot, const std::string& newFrame)
+    {
+        ARMARX_CHECK_NOT_NULL(robot);
+        changeFrame(*robot, newFrame);
+    }
+
+    void FramedDirection::changeFrame(const VirtualRobot::Robot& robot, const std::string& newFrame)
     {
         if (frame == "")
         {
@@ -129,14 +141,14 @@ namespace armarx
             return;
         }
 
-        if (!robot->hasRobotNode(newFrame))
+        if (!robot.hasRobotNode(newFrame))
         {
-            throw LocalException() << "The requested frame '" << newFrame << "' does not exist in the robot " << robot->getName();
+            throw LocalException() << "The requested frame '" << newFrame << "' does not exist in the robot " << robot.getName();
         }
 
-        if (frame != GlobalFrame && !robot->hasRobotNode(frame))
+        if (frame != GlobalFrame && !robot.hasRobotNode(frame))
         {
-            throw LocalException() << "The current frame '" << frame << "' does not exist in the robot " << robot->getName();
+            throw LocalException() << "The current frame '" << frame << "' does not exist in the robot " << robot.getName();
         }
 
 
@@ -151,7 +163,7 @@ namespace armarx
         y = newVec(1);
         z = newVec(2);
         frame = newFrame;
-        agent = robot->getName();
+        agent = robot.getName();
     }
 
     void FramedDirection::changeToGlobal(const SharedRobotInterfacePrx& referenceRobot)
@@ -161,14 +173,20 @@ namespace armarx
     }
 
     void FramedDirection::changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeToGlobal(*referenceRobot);
+    }
+
+    void FramedDirection::changeToGlobal(const VirtualRobot::Robot& referenceRobot)
     {
         if (frame == GlobalFrame)
         {
             return;
         }
 
-        changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
-        Eigen::Vector3f pos = referenceRobot->getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen();
+        changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
+        Eigen::Vector3f pos = referenceRobot.getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen();
         x = pos[0];
         y = pos[1];
         z = pos[2];
@@ -182,6 +200,11 @@ namespace armarx
         return toGlobal(sharedRobot);
     }
     FramedDirectionPtr FramedDirection::toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobal(*referenceRobot);
+    }
+    FramedDirectionPtr FramedDirection::toGlobal(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedDirectionPtr newDirection = FramedDirectionPtr::dynamicCast(this->clone());
         newDirection->changeToGlobal(referenceRobot);
@@ -194,6 +217,11 @@ namespace armarx
         return toGlobalEigen(sharedRobot);
     }
     Eigen::Vector3f FramedDirection::toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobalEigen(*referenceRobot);
+    }
+    Eigen::Vector3f FramedDirection::toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedDirection newDirection(toEigen(), frame, agent);
         newDirection.changeToGlobal(referenceRobot);
@@ -206,9 +234,14 @@ namespace armarx
         return toRootFrame(sharedRobot);
     }
     FramedDirectionPtr FramedDirection::toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootFrame(*referenceRobot);
+    }
+    FramedDirectionPtr FramedDirection::toRootFrame(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedDirectionPtr newDirection = FramedDirectionPtr::dynamicCast(this->clone());
-        newDirection->changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newDirection->changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newDirection;
     }
 
@@ -218,9 +251,14 @@ namespace armarx
         return toRootEigen(sharedRobot);
     }
     Eigen::Vector3f FramedDirection::toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootEigen(*referenceRobot);
+    }
+    Eigen::Vector3f FramedDirection::toRootEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedDirection newDirection(toEigen(), frame, agent);
-        newDirection.changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newDirection.changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newDirection.toEigen();
     }
 
@@ -231,21 +269,21 @@ namespace armarx
         return s.str();
     }
 
-    Eigen::Matrix4f FramedDirection::__GetRotationBetweenFrames(const std::string& oldFrame, const std::string& newFrame, VirtualRobot::RobotPtr robotState)
+    Eigen::Matrix4f FramedDirection::__GetRotationBetweenFrames(const std::string& oldFrame, const std::string& newFrame, const VirtualRobot::Robot& robotState)
     {
         Eigen::Matrix4f toNewFrame;
 
         if (oldFrame == GlobalFrame)
         {
-            auto node = robotState->getRobotNode(newFrame);
+            auto node = robotState.getRobotNode(newFrame);
             ARMARX_CHECK_EXPRESSION(node) << newFrame;
             toNewFrame = node->getGlobalPose();
         }
         else
         {
-            auto node = robotState->getRobotNode(oldFrame);
-            ARMARX_CHECK_EXPRESSION(node) << "old frame: " + oldFrame + ValueToString(robotState->getConfig()->getRobotNodeJointValueMap());
-            auto newNode = robotState->getRobotNode(newFrame);
+            auto node = robotState.getRobotNode(oldFrame);
+            ARMARX_CHECK_EXPRESSION(node) << "old frame: " + oldFrame + ValueToString(robotState.getConfig()->getRobotNodeJointValueMap());
+            auto newNode = robotState.getRobotNode(newFrame);
             ARMARX_CHECK_EXPRESSION(newNode) << newFrame;
             toNewFrame = node->getTransformationTo(newNode);
         }
@@ -369,6 +407,12 @@ namespace armarx
     }
 
     void FramedPose::changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeFrame(*referenceRobot, newFrame);
+    }
+
+    void FramedPose::changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame)
     {
         if (newFrame == frame)
         {
@@ -383,32 +427,32 @@ namespace armarx
 
         Eigen::Matrix4f oldFrameTransformation = Eigen::Matrix4f::Identity();
 
-        if (frame != GlobalFrame and !referenceRobot->hasRobotNode(frame))
+        if (frame != GlobalFrame and !referenceRobot.hasRobotNode(frame))
         {
-            throw LocalException() << "The current frame '" << frame << "' does not exists in the robot " << referenceRobot->getName();
+            throw LocalException() << "The current frame '" << frame << "' does not exists in the robot " << referenceRobot.getName();
         }
-        if (!referenceRobot->hasRobotNode(newFrame))
+        if (!referenceRobot.hasRobotNode(newFrame))
         {
-            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot->getName();
+            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot.getName();
         }
 
         if (frame != GlobalFrame)
         {
-            oldFrameTransformation = referenceRobot->getRobotNode(frame)->getPoseInRootFrame();
+            oldFrameTransformation = referenceRobot.getRobotNode(frame)->getPoseInRootFrame();
         }
         else
         {
-            oldFrameTransformation = referenceRobot->getRootNode()->getGlobalPose().inverse();
+            oldFrameTransformation = referenceRobot.getRootNode()->getGlobalPose().inverse();
         }
 
         Eigen::Matrix4f newPose =
-            (referenceRobot->getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * toEigen();
+            (referenceRobot.getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * toEigen();
 
         orientation = new Quaternion(newPose);
         Eigen::Vector3f pos = newPose.block<3, 1>(0, 3);
         position = new Vector3(pos);
         frame = newFrame;
-        agent = referenceRobot->getName();
+        agent = referenceRobot.getName();
         init();
     }
 
@@ -418,16 +462,20 @@ namespace armarx
         changeToGlobal(sharedRobot);
 
     }
-
     void FramedPose::changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeToGlobal(*referenceRobot);
+    }
+    void FramedPose::changeToGlobal(const VirtualRobot::Robot& referenceRobot)
     {
         if (frame == GlobalFrame)
         {
             return;
         }
 
-        changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
-        Eigen::Matrix4f global = referenceRobot->getRootNode()->getGlobalPose();
+        changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
+        Eigen::Matrix4f global = referenceRobot.getRootNode()->getGlobalPose();
         const Eigen::Matrix4f pose = global * toEigen();
         position->x = pose(0, 3);
         position->y = pose(1, 3);
@@ -447,6 +495,11 @@ namespace armarx
         return toGlobal(sharedRobot);
     }
     FramedPosePtr FramedPose::toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobal(*referenceRobot);
+    }
+    FramedPosePtr FramedPose::toGlobal(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPosePtr newPose = FramedPosePtr::dynamicCast(this->clone());
         newPose->changeToGlobal(referenceRobot);
@@ -459,6 +512,11 @@ namespace armarx
         return toGlobalEigen(sharedRobot);
     }
     Eigen::Matrix4f FramedPose::toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobalEigen(*referenceRobot);
+    }
+    Eigen::Matrix4f FramedPose::toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPose newPose(toEigen(), frame, agent);
         newPose.changeToGlobal(referenceRobot);
@@ -471,9 +529,14 @@ namespace armarx
         return toRootFrame(sharedRobot);
     }
     FramedPosePtr FramedPose::toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootFrame(*referenceRobot);
+    }
+    FramedPosePtr FramedPose::toRootFrame(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPosePtr newPose = FramedPosePtr::dynamicCast(this->clone());
-        newPose->changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newPose->changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newPose;
     }
 
@@ -483,9 +546,14 @@ namespace armarx
         return toRootEigen(sharedRobot);
     }
     Eigen::Matrix4f FramedPose::toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootEigen(*referenceRobot);
+    }
+    Eigen::Matrix4f FramedPose::toRootEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPose newPose(toEigen(), frame, agent);
-        newPose.changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newPose.changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newPose.toEigen();
     }
 
@@ -575,6 +643,12 @@ namespace armarx
     }
 
     void FramedPosition::changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeFrame(*referenceRobot, newFrame);
+    }
+
+    void FramedPosition::changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame)
     {
         if (newFrame == frame)
         {
@@ -596,30 +670,30 @@ namespace armarx
 
         Eigen::Matrix4f oldFrameTransformation = Eigen::Matrix4f::Identity();
 
-        if (!referenceRobot->hasRobotNode(newFrame))
+        if (!referenceRobot.hasRobotNode(newFrame))
         {
-            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot->getName();
+            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot.getName();
         }
 
         if (frame != GlobalFrame)
         {
-            oldFrameTransformation = referenceRobot->getRobotNode(frame)->getPoseInRootFrame();
+            oldFrameTransformation = referenceRobot.getRobotNode(frame)->getPoseInRootFrame();
         }
         else
         {
-            oldFrameTransformation = referenceRobot->getRootNode()->getGlobalPose().inverse();
+            oldFrameTransformation = referenceRobot.getRootNode()->getGlobalPose().inverse();
         }
 
         Eigen::Matrix4f oldPose = Eigen::Matrix4f::Identity();
         oldPose.block<3, 1>(0, 3) = toEigen();
         Eigen::Matrix4f newPose =
-            (referenceRobot->getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * oldPose;
+            (referenceRobot.getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * oldPose;
 
         Eigen::Vector3f pos = newPose.block<3, 1>(0, 3);
         x = pos[0];
         y = pos[1];
         z = pos[2];
-        agent = referenceRobot->getName();
+        agent = referenceRobot.getName();
         frame = newFrame;
     }
 
@@ -628,17 +702,21 @@ namespace armarx
         VirtualRobot::RobotPtr sharedRobot(new RemoteRobot(referenceRobot));
         changeToGlobal(sharedRobot);
     }
-
     void FramedPosition::changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeToGlobal(*referenceRobot);
+    }
+    void FramedPosition::changeToGlobal(const VirtualRobot::Robot& referenceRobot)
     {
         if (frame == GlobalFrame)
         {
             return;
         }
 
-        changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
-        Eigen::Vector3f pos = referenceRobot->getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen()
-                              + referenceRobot->getRootNode()->getGlobalPose().block<3, 1>(0, 3);
+        changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
+        Eigen::Vector3f pos = referenceRobot.getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen()
+                              + referenceRobot.getRootNode()->getGlobalPose().block<3, 1>(0, 3);
         x = pos[0];
         y = pos[1];
         z = pos[2];
@@ -652,6 +730,11 @@ namespace armarx
         return toGlobal(sharedRobot);
     }
     FramedPositionPtr FramedPosition::toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobal(*referenceRobot);
+    }
+    FramedPositionPtr FramedPosition::toGlobal(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPositionPtr newPosition = FramedPositionPtr::dynamicCast(this->clone());
         newPosition->changeToGlobal(referenceRobot);
@@ -664,6 +747,11 @@ namespace armarx
         return toGlobalEigen(sharedRobot);
     }
     Eigen::Vector3f FramedPosition::toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobalEigen(*referenceRobot);
+    }
+    Eigen::Vector3f FramedPosition::toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPosition newPosition(toEigen(), frame, agent);
         newPosition.changeToGlobal(referenceRobot);
@@ -676,9 +764,14 @@ namespace armarx
         return toRootFrame(sharedRobot);
     }
     FramedPositionPtr FramedPosition::toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootFrame(*referenceRobot);
+    }
+    FramedPositionPtr FramedPosition::toRootFrame(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPositionPtr newPosition = FramedPositionPtr::dynamicCast(this->clone());
-        newPosition->changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newPosition->changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newPosition;
     }
 
@@ -688,9 +781,14 @@ namespace armarx
         return toRootEigen(sharedRobot);
     }
     Eigen::Vector3f FramedPosition::toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootEigen(*referenceRobot);
+    }
+    Eigen::Vector3f FramedPosition::toRootEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedPosition newPosition(toEigen(), frame, agent);
-        newPosition.changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newPosition.changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newPosition.toEigen();
     }
 
@@ -829,6 +927,12 @@ namespace armarx
     }
 
     void FramedOrientation::changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeFrame(*referenceRobot, newFrame);
+    }
+
+    void FramedOrientation::changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame)
     {
         if (newFrame == frame)
         {
@@ -843,32 +947,32 @@ namespace armarx
 
         Eigen::Matrix4f oldFrameTransformation = Eigen::Matrix4f::Identity();
 
-        if (!referenceRobot->hasRobotNode(newFrame))
+        if (!referenceRobot.hasRobotNode(newFrame))
         {
-            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot->getName();
+            throw LocalException() << "The requested frame '" << newFrame << "' does not exists in the robot " << referenceRobot.getName();
         }
 
         if (frame != GlobalFrame)
         {
-            oldFrameTransformation = referenceRobot->getRobotNode(frame)->getPoseInRootFrame();
+            oldFrameTransformation = referenceRobot.getRobotNode(frame)->getPoseInRootFrame();
         }
         else
         {
-            oldFrameTransformation = referenceRobot->getRootNode()->getGlobalPose().inverse();
+            oldFrameTransformation = referenceRobot.getRootNode()->getGlobalPose().inverse();
         }
 
         Eigen::Matrix4f oldPose = Eigen::Matrix4f::Identity();
         oldPose.block<3, 3>(0, 0) = toEigen();
 
         Eigen::Matrix4f newPose =
-            (referenceRobot->getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * oldPose;
+            (referenceRobot.getRobotNode(newFrame)->getPoseInRootFrame().inverse() * oldFrameTransformation) * oldPose;
 
         Eigen::Quaternionf quat(newPose.block<3, 3>(0, 0));
         qw = quat.w();
         qx = quat.x();
         qy = quat.y();
         qz = quat.z();
-        agent = referenceRobot->getName();
+        agent = referenceRobot.getName();
         frame = newFrame;
     }
 
@@ -879,14 +983,19 @@ namespace armarx
     }
 
     void FramedOrientation::changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot)
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        changeToGlobal(*referenceRobot);
+    }
+    void FramedOrientation::changeToGlobal(const VirtualRobot::Robot& referenceRobot)
     {
         if (frame == GlobalFrame)
         {
             return;
         }
 
-        changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
-        Eigen::Matrix3f rot = referenceRobot->getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen();
+        changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
+        Eigen::Matrix3f rot = referenceRobot.getRootNode()->getGlobalPose().block<3, 3>(0, 0) * toEigen();
         Eigen::Quaternionf quat(rot);
         qw = quat.w();
         qx = quat.x();
@@ -902,6 +1011,11 @@ namespace armarx
         return toGlobal(sharedRobot);
     }
     FramedOrientationPtr FramedOrientation::toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobal(*referenceRobot);
+    }
+    FramedOrientationPtr FramedOrientation::toGlobal(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedOrientationPtr newOrientation = FramedOrientationPtr::dynamicCast(this->clone());
         newOrientation->changeToGlobal(referenceRobot);
@@ -914,6 +1028,11 @@ namespace armarx
         return toGlobalEigen(sharedRobot);
     }
     Eigen::Matrix3f FramedOrientation::toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toGlobalEigen(*referenceRobot);
+    }
+    Eigen::Matrix3f FramedOrientation::toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedOrientation newOrientation(toEigen(), frame, agent);
         newOrientation.changeToGlobal(referenceRobot);
@@ -926,9 +1045,14 @@ namespace armarx
         return toRootFrame(sharedRobot);
     }
     FramedOrientationPtr FramedOrientation::toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootFrame(*referenceRobot);
+    }
+    FramedOrientationPtr FramedOrientation::toRootFrame(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedOrientationPtr newOrientation = FramedOrientationPtr::dynamicCast(this->clone());
-        newOrientation->changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newOrientation->changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newOrientation;
     }
 
@@ -938,9 +1062,14 @@ namespace armarx
         return toRootEigen(sharedRobot);
     }
     Eigen::Matrix3f FramedOrientation::toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const
+    {
+        ARMARX_CHECK_NOT_NULL(referenceRobot);
+        return toRootEigen(*referenceRobot);
+    }
+    Eigen::Matrix3f FramedOrientation::toRootEigen(const VirtualRobot::Robot& referenceRobot) const
     {
         FramedOrientation newOrientation(toEigen(), frame, agent);
-        newOrientation.changeFrame(referenceRobot, referenceRobot->getRootNode()->getName());
+        newOrientation.changeFrame(referenceRobot, referenceRobot.getRootNode()->getName());
         return newOrientation.toEigen();
     }
 
diff --git a/source/RobotAPI/libraries/core/FramedPose.h b/source/RobotAPI/libraries/core/FramedPose.h
index e0ca6fdaa..01f5c9c6a 100644
--- a/source/RobotAPI/libraries/core/FramedPose.h
+++ b/source/RobotAPI/libraries/core/FramedPose.h
@@ -93,18 +93,25 @@ namespace armarx
 
         std::string getFrame() const;
         static FramedDirectionPtr ChangeFrame(const VirtualRobot::RobotPtr& robot, const FramedDirection& framedVec, const std::string& newFrame);
+        static FramedDirectionPtr ChangeFrame(const VirtualRobot::Robot& robot, const FramedDirection& framedVec, const std::string& newFrame);
         void changeFrame(const VirtualRobot::RobotPtr& robot, const std::string& newFrame);
+        void changeFrame(const VirtualRobot::Robot& robot, const std::string& newFrame);
 
         void changeToGlobal(const SharedRobotInterfacePrx& referenceRobot);
         void changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot);
+        void changeToGlobal(const VirtualRobot::Robot& referenceRobot);
         FramedDirectionPtr toGlobal(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedDirectionPtr toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedDirectionPtr toGlobal(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Vector3f toGlobalEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Vector3f toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Vector3f toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const;
         FramedDirectionPtr toRootFrame(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedDirectionPtr toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedDirectionPtr toRootFrame(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Vector3f toRootEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Vector3f toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Vector3f toRootEigen(const VirtualRobot::Robot& referenceRobot) const;
 
         // inherited from VariantDataClass
         Ice::ObjectPtr ice_clone() const override;
@@ -120,7 +127,7 @@ namespace armarx
         void deserialize(const armarx::ObjectSerializerBasePtr& serializer, const ::Ice::Current& = Ice::emptyCurrent) override;
 
     private:
-        static Eigen::Matrix4f __GetRotationBetweenFrames(const std::string& oldFrame, const std::string& newFrame, VirtualRobot::RobotPtr robotState);
+        static Eigen::Matrix4f __GetRotationBetweenFrames(const std::string& oldFrame, const std::string& newFrame, const VirtualRobot::Robot& robotState);
     };
 
     class FramedPosition;
@@ -149,16 +156,22 @@ namespace armarx
 
         void changeFrame(const SharedRobotInterfacePrx& referenceRobot, const std::string& newFrame);
         void changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame);
+        void changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame);
         void changeToGlobal(const SharedRobotInterfacePrx& referenceRobot);
         void changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot);
+        void changeToGlobal(const VirtualRobot::Robot& referenceRobot);
         FramedPositionPtr toGlobal(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedPositionPtr toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedPositionPtr toGlobal(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Vector3f toGlobalEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Vector3f toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Vector3f toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const;
         FramedPositionPtr toRootFrame(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedPositionPtr toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedPositionPtr toRootFrame(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Vector3f toRootEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Vector3f toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Vector3f toRootEigen(const VirtualRobot::Robot& referenceRobot) const;
 
         // inherited from VariantDataClass
         Ice::ObjectPtr ice_clone() const override;
@@ -207,16 +220,22 @@ namespace armarx
 
         void changeFrame(const SharedRobotInterfacePrx& referenceRobot, const std::string& newFrame);
         void changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame);
+        void changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame);
         void changeToGlobal(const SharedRobotInterfacePrx& referenceRobot);
         void changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot);
+        void changeToGlobal(const VirtualRobot::Robot& referenceRobot);
         FramedOrientationPtr toGlobal(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedOrientationPtr toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedOrientationPtr toGlobal(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Matrix3f toGlobalEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Matrix3f toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Matrix3f toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const;
         FramedOrientationPtr toRootFrame(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedOrientationPtr toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedOrientationPtr toRootFrame(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Matrix3f toRootEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Matrix3f toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Matrix3f toRootEigen(const VirtualRobot::Robot& referenceRobot) const;
 
         friend std::ostream& operator<<(std::ostream& stream, const FramedOrientation& rhs);
 
@@ -264,20 +283,28 @@ namespace armarx
 
         void changeFrame(const SharedRobotInterfacePrx& referenceRobot, const std::string& newFrame);
         void changeFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame);
+        void changeFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame);
         void changeToGlobal(const SharedRobotInterfacePrx& referenceRobot);
         void changeToGlobal(const VirtualRobot::RobotPtr& referenceRobot);
+        void changeToGlobal(const VirtualRobot::Robot& referenceRobot);
         FramedPosePtr toGlobal(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedPosePtr toGlobal(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedPosePtr toGlobal(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Matrix4f toGlobalEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Matrix4f toGlobalEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Matrix4f toGlobalEigen(const VirtualRobot::Robot& referenceRobot) const;
         FramedPosePtr toRootFrame(const SharedRobotInterfacePrx& referenceRobot) const;
         FramedPosePtr toRootFrame(const VirtualRobot::RobotPtr& referenceRobot) const;
+        FramedPosePtr toRootFrame(const VirtualRobot::Robot& referenceRobot) const;
         Eigen::Matrix4f toRootEigen(const SharedRobotInterfacePrx& referenceRobot) const;
         Eigen::Matrix4f toRootEigen(const VirtualRobot::RobotPtr& referenceRobot) const;
+        Eigen::Matrix4f toRootEigen(const VirtualRobot::Robot& referenceRobot) const;
         FramedPosePtr toFrame(const SharedRobotInterfacePrx& referenceRobot, const std::string& newFrame) const;
         FramedPosePtr toFrame(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame) const;
+        FramedPosePtr toFrame(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame) const;
         Eigen::Matrix4f toFrameEigen(const SharedRobotInterfacePrx& referenceRobot, const std::string& newFrame) const;
         Eigen::Matrix4f toFrameEigen(const VirtualRobot::RobotPtr& referenceRobot, const std::string& newFrame) const;
+        Eigen::Matrix4f toFrameEigen(const VirtualRobot::Robot& referenceRobot, const std::string& newFrame) const;
 
         friend std::ostream& operator<<(std::ostream& stream, const FramedPose& rhs);
         FramedPositionPtr getPosition() const;
-- 
GitLab