diff --git a/source/RobotAPI/components/ArViz/CMakeLists.txt b/source/RobotAPI/components/ArViz/CMakeLists.txt
index f3cdfc0f709b19c99471e1ecc64ed3396ea6653f..e765f4162f65e1daaff52551166e489a4f3cdd60 100644
--- a/source/RobotAPI/components/ArViz/CMakeLists.txt
+++ b/source/RobotAPI/components/ArViz/CMakeLists.txt
@@ -26,6 +26,7 @@ Coin/VisualizerPose.h
 Coin/VisualizerLine.h
 Coin/VisualizerText.h
 Coin/VisualizerArrow.h
+Coin/VisualizerArrowCircle.h
 
 Coin/Visualizer.h
 )
diff --git a/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.cpp b/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.cpp
index b5223f6b815de51c910fb977c13581032090b359..455821397c7de106a3133fb0763c4f69817dbf60 100644
--- a/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.cpp
+++ b/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.cpp
@@ -21,19 +21,19 @@ namespace armarx
 
                 result.transform = new SoTransform;
                 result.material = new SoMaterial;
-                result.element = createElement_();
+                result.element.reset(createElement_());
 
                 result.seperator = new SoSeparator;
                 result.seperator->addChild(result.units);
                 result.seperator->addChild(result.transform);
                 result.seperator->addChild(result.material);
-                result.seperator->addChild(result.element);
+                result.seperator->addChild(result.element->node_);
 
                 update(element, &result);
                 return result;
             }
 
-            void ElementVisualizer::update(Element const& element, ElementVisualization* visu)
+            bool ElementVisualizer::update(Element const& element, ElementVisualization* visu)
             {
                 if (visu->transform)
                 {
@@ -53,8 +53,9 @@ namespace armarx
                 }
                 if (visu->element)
                 {
-                    updateElement_(element, visu->element);
+                    return updateElement_(element, visu->element.get());
                 }
+                return false;
             }
 
         }
diff --git a/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.h b/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.h
index 7326ced15c72daf5115cd91d54e05fd8a03feca3..d2db18926ec6977492dafa5d36d381148784dbcb 100644
--- a/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.h
+++ b/source/RobotAPI/components/ArViz/Coin/ElementVisualizer.h
@@ -5,6 +5,8 @@
 #include <Inventor/nodes/SoUnits.h>
 #include <Inventor/nodes/SoTransform.h>
 
+#include <memory>
+
 namespace armarx
 {
     namespace viz
@@ -14,13 +16,33 @@ namespace armarx
 
         namespace coin
         {
+            struct ElementVisuData
+            {
+                virtual ~ElementVisuData() = default;
+
+                SoNode* node_ = nullptr;
+            };
+
+            template <typename NodeT>
+            struct TypedVisuData : ElementVisuData
+            {
+                TypedVisuData()
+                {
+                    node_ = new NodeT;
+                }
+                NodeT* node()
+                {
+                    return static_cast<NodeT*>(node_);
+                }
+            };
+
             struct ElementVisualization
             {
                 SoSeparator* seperator = nullptr;
                 SoUnits* units = nullptr;
                 SoTransform* transform = nullptr;
                 SoMaterial* material = nullptr;
-                SoNode* element = nullptr;
+                std::unique_ptr<ElementVisuData> element;
             };
 
             class ElementVisualizer
@@ -29,32 +51,33 @@ namespace armarx
                 virtual ~ElementVisualizer() = default;
 
                 virtual ElementVisualization create(Element const& element) final;
-                virtual void update(Element const& element, ElementVisualization* visu) final;
+                virtual bool update(Element const& element, ElementVisualization* visu) final;
 
-                virtual SoNode* createElement_() = 0;
-                virtual void updateElement_(Element const& element, SoNode* node) = 0;
+                virtual ElementVisuData* createElement_() = 0;
+                virtual bool updateElement_(Element const& element, ElementVisuData* data) = 0;
             };
 
-            template <typename BaseT, typename ElementT, typename NodeT>
+            template <typename BaseT, typename ElementT, typename DataT>
             class TypedElementVisualizer : public ElementVisualizer
             {
             public:
                 using ElementType = ElementT;
-                using NodeType = NodeT;
+                using DataType = DataT;
 
-                SoNode* createElement_() override
+                DataType* createElement_() override
                 {
-                    return new NodeT;
+                    return new DataType;
                 }
 
-                void updateElement_(Element const& element_, SoNode* node_)
+                bool updateElement_(Element const& element_, ElementVisuData* data_) override
                 {
                     auto const& element = static_cast<ElementType const&>(element_);
-                    auto* node = dynamic_cast<NodeType*>(node_);
-                    if (node)
+                    auto* data = dynamic_cast<DataType*>(data_);
+                    if (data)
                     {
-                        static_cast<BaseT*>(this)->updateElement(element, node);
+                        static_cast<BaseT*>(this)->updateElement(element, data);
                     }
+                    return data != nullptr;
                 }
             };
 
diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
index a038cb8a8111fdcd791268e05884e699c67f7a3c..f44a31738783ad0ac574d153887e37b599204093 100644
--- a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
+++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
@@ -7,6 +7,7 @@
 #include "VisualizerLine.h"
 #include "VisualizerText.h"
 #include "VisualizerArrow.h"
+#include "VisualizerArrowCircle.h"
 
 #include <ArmarXCore/core/logging/Logging.h>
 
@@ -53,6 +54,7 @@ namespace armarx
             registerVisualizer<VisualizerLine>();
             registerVisualizer<VisualizerText>();
             registerVisualizer<VisualizerArrow>();
+            registerVisualizer<VisualizerArrowCircle>();
 
             root = new SoSeparator;
 
@@ -114,7 +116,7 @@ namespace armarx
 
                 CoinLayer newLayer;
                 newLayer.node = coinNode;
-                layerIt = layers.emplace(layerID, newLayer).first;
+                layerIt = layers.emplace(layerID, std::move(newLayer)).first;
             }
 
             CoinLayer& layer = layerIt->second;
@@ -178,7 +180,7 @@ namespace armarx
                 if (elementVisu.seperator)
                 {
                     layer.node->addChild(elementVisu.seperator);
-                    layer.elements[updatedElement.id] = elementVisu;
+                    layer.elements[updatedElement.id] = std::move(elementVisu);
                 }
                 else
                 {
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerArrow.h b/source/RobotAPI/components/ArViz/Coin/VisualizerArrow.h
index b00f9062874219f5fbc7cd3f2d665e94406b7227..d376e5cd9bcfe7a1bb30dd89b08e1d6909f32b12 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerArrow.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerArrow.h
@@ -8,63 +8,48 @@
 #include <Inventor/nodes/SoSphere.h>
 #include <Inventor/nodes/SoTranslation.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataArrow : TypedVisuData<SoSeparator>
     {
-        namespace coin
+        VisuDataArrow()
         {
+            tr = new SoTranslation;
+            c = new SoCylinder();
+            transl = new SoTranslation;
+            cone = new SoCone();
+
+            auto* sep = node();
+            sep->addChild(tr);
+            sep->addChild(c);
+            sep->addChild(transl);
+            sep->addChild(cone);
+        }
 
-            struct VisualizerArrow: TypedElementVisualizer<VisualizerArrow, ElementArrow, SoSeparator>
-            {
-                void updateElement(ElementType const& element, NodeType* node)
-                {
-
-                    float coneHeight = element.width * 6.0f;
-                    float coneBottomRadius = element.width * 2.5f;
-                    float baseLength = element.length - coneHeight;
-                    baseLength = std::max(0.0f, baseLength);
-
-                    //                    SbVec3f objNormal(n2(0), n2(1), n2(2));
-                    //                    SbMatrix objNormalTrafo;
-                    //                    objNormalTrafo.makeIdentity();
-                    //                    SbRotation objNormalRot(SbVec3f(0, 1.0f, 0), objNormal);
-
-                    // get rid of warnings when angle==0
-                    //                    SbVec3f axis;
-                    //                    float angle;
-                    //                    objNormalRot.getValue(axis, angle);
-
-                    //                    if (angle != 0)
-                    //                    {
-                    //                        objNormalTrafo.setRotate(objNormalRot);
-                    //                    }
-
-
-                    SoTranslation* tr = new SoTranslation;
-                    tr->translation.setValue(0, baseLength * 0.5f, 0);
-
-
-                    SoCylinder* c = new SoCylinder();
-                    c->radius = element.width;
-                    c->height = baseLength;
+        SoTranslation* tr;
+        SoCylinder* c;
+        SoTranslation* transl;
+        SoCone* cone;
+    };
 
+    struct VisualizerArrow : TypedElementVisualizer<VisualizerArrow, ElementArrow, VisuDataArrow>
+    {
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            float coneHeight = element.width * 6.0f;
+            float coneBottomRadius = element.width * 2.5f;
+            float baseLength = element.length - coneHeight;
+            baseLength = std::max(0.0f, baseLength);
 
-                    SoTranslation* transl = new SoTranslation;
-                    transl->translation.setValue(0, element.length * 0.5f, 0);
+            data->tr->translation.setValue(0, baseLength * 0.5f, 0);
 
-                    SoCone* cone = new SoCone();
-                    cone->bottomRadius.setValue(coneBottomRadius);
-                    cone->height.setValue(coneHeight);
+            data->c->radius = element.width;
+            data->c->height = baseLength;
 
-                    node->removeAllChildren();
-                    node->addChild(tr);
-                    node->addChild(c);
-                    node->addChild(transl);
-                    node->addChild(cone);
-                }
-            };
+            data->transl->translation.setValue(0, element.length * 0.5f, 0);
 
+            data->cone->bottomRadius.setValue(coneBottomRadius);
+            data->cone->height.setValue(coneHeight);
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerArrowCircle.h b/source/RobotAPI/components/ArViz/Coin/VisualizerArrowCircle.h
new file mode 100644
index 0000000000000000000000000000000000000000..fe5cc902755c63f1ef0a70c944c98d92caf95a47
--- /dev/null
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerArrowCircle.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include "ElementVisualizer.h"
+
+#include <RobotAPI/interface/ArViz/Elements.h>
+#include <Inventor/nodes/SoCone.h>
+#include <Inventor/nodes/SoCylinder.h>
+#include <Inventor/nodes/SoSphere.h>
+#include <Inventor/nodes/SoTranslation.h>
+
+#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
+#include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationNode.h>
+
+namespace armarx::viz::coin
+{
+    struct VisuDataArrowCircle : TypedVisuData<SoSeparator>
+    {
+
+    };
+
+    struct VisualizerArrowCircle: TypedElementVisualizer<VisualizerArrowCircle, ElementArrowCircle, VisuDataArrowCircle>
+    {
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            auto* node = data->node();
+
+            int rings = 32;
+
+            float completion = std::min<float>(1.0f, std::max(-1.0f, element.completion));
+            int sign = completion >= 0 ? 1 : -1;
+            float torusCompletion = completion - 1.0f / rings * sign;
+            if (torusCompletion * sign < 0)
+            {
+                torusCompletion = 0;
+            }
+            auto color = element.color;
+            const float conv = 1.0f / 255.0f;
+            color.r *= conv;
+            color.g *= conv;
+            color.b *= conv;
+            color.a *= conv;
+            // This does not play well with
+            auto torusNode = VirtualRobot::CoinVisualizationFactory().createTorus(
+                                 element.radius, element.width, torusCompletion,
+                                 color.r, color.g, color.b, 0.0f,
+                                 8, rings);
+            SoNode* torus = dynamic_cast<VirtualRobot::CoinVisualizationNode&>(*torusNode).getCoinVisualization();
+
+
+            float angle0 = (float)(rings - 2) / rings * 2 * M_PI * completion;
+            float x0 = element.radius * cos(angle0);
+            float y0 = element.radius * sin(angle0);
+            float angle1 = (float)(rings - 1) / rings * 2 * M_PI * completion;
+
+            SoSeparator* subSep = new SoSeparator();
+            SoTransform* tr = new SoTransform;
+            tr->translation.setValue(x0, y0, 0);
+
+            tr->rotation.setValue(SbVec3f(0, 0, 1), angle1);
+            subSep->addChild(tr);
+
+            //subSep->addChild(CreateArrow(Eigen::Vector3f::UnitY()*sign, 0, element.width, Color(1.0f, 1.0f, 1.0f)));
+
+            node->removeAllChildren();
+            node->addChild(torus);
+            node->addChild(subSep);
+
+        }
+    };
+}
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerBox.h b/source/RobotAPI/components/ArViz/Coin/VisualizerBox.h
index b0ccf472689c7e5bb4d5ac8e562171a3e9c0b660..d6c7e0607810b133829d3d84089738edd80b10e1 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerBox.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerBox.h
@@ -5,23 +5,23 @@
 #include <RobotAPI/interface/ArViz/Elements.h>
 #include <Inventor/nodes/SoCube.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataBox : TypedVisuData<SoCube>
     {
-        namespace coin
+
+    };
+
+    class VisualizerBox : public TypedElementVisualizer<VisualizerBox, ElementBox, VisuDataBox>
+    {
+    public:
+        void updateElement(const ElementType& element, DataType* data)
         {
+            auto* node = data->node();
 
-            class VisualizerBox : public TypedElementVisualizer<VisualizerBox, ElementBox, SoCube>
-            {
-            public:
-                void updateElement(const ElementType& element, NodeType* node)
-                {
-                    node->width = element.size.e0;
-                    node->height = element.size.e1;
-                    node->depth = element.size.e2;
-                }
-            };
+            node->width = element.size.e0;
+            node->height = element.size.e1;
+            node->depth = element.size.e2;
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerCylinder.h b/source/RobotAPI/components/ArViz/Coin/VisualizerCylinder.h
index b8e83e3f64daf0dfdea4d2a66070d6c4b9726ffa..a9bbce8db0451ef5f66405e286832ef0d6407d6a 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerCylinder.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerCylinder.h
@@ -5,23 +5,22 @@
 #include <RobotAPI/interface/ArViz/Elements.h>
 #include <Inventor/nodes/SoCylinder.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataCylinder : TypedVisuData<SoCylinder>
     {
-        namespace coin
-        {
 
-            class VisualizerCylinder : public TypedElementVisualizer<VisualizerCylinder, ElementCylinder, SoCylinder>
-            {
-            public:
-                void updateElement(ElementType const& element, NodeType* node)
-                {
-                    node->radius = element.radius;
-                    node->height = element.height;
-                }
-            };
+    };
+
+    class VisualizerCylinder : public TypedElementVisualizer<VisualizerCylinder, ElementCylinder, VisuDataCylinder>
+    {
+    public:
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            auto* node = data->node();
 
+            node->radius = element.radius;
+            node->height = element.height;
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerLine.h b/source/RobotAPI/components/ArViz/Coin/VisualizerLine.h
index 81b007ca3b45ebd266b42d230cd1ef05c9b75ff9..b6d8465b0c55f3015b2e060cca8fa1ca2c1bfbbe 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerLine.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerLine.h
@@ -8,37 +8,38 @@
 #include <Inventor/nodes/SoDrawStyle.h>
 #include <Inventor/nodes/SoCoordinate3.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataLine : TypedVisuData<SoSeparator>
     {
-        namespace coin
+        VisuDataLine()
         {
+            lineStyle = new SoDrawStyle;
+            coordinate3 = new SoCoordinate3;
+            SoLineSet* lineSet = new SoLineSet;
+            lineSet->numVertices.setValue(2);
+            lineSet->startIndex.setValue(0);
+
+            auto* sep = node();
+            sep->addChild(lineStyle);
+            sep->addChild(coordinate3);
+            sep->addChild(lineSet);
+        }
+
+        SoDrawStyle* lineStyle;
+        SoCoordinate3* coordinate3;
+    };
 
-            struct VisualizerLine: TypedElementVisualizer<VisualizerLine, ElementLine, SoSeparator>
-            {
-                void updateElement(ElementType const& element, NodeType* node)
-                {
-                    SoDrawStyle* lineSolutionStyle = new SoDrawStyle();
-                    lineSolutionStyle->lineWidth.setValue(element.lineWidth);
-
-                    SbVec3f from(element.from.e0, element.from.e1, element.from.e2);
-                    SbVec3f to(element.to.e0, element.to.e1, element.to.e2);
-                    SoCoordinate3* coordinate3 = new SoCoordinate3;
-                    coordinate3->point.set1Value(0, from);
-                    coordinate3->point.set1Value(1, to);
-
-                    SoLineSet* lineSet = new SoLineSet;
-                    lineSet->numVertices.setValue(2);
-                    lineSet->startIndex.setValue(0);
-
-                    node->removeAllChildren();
-                    node->addChild(lineSolutionStyle);
-                    node->addChild(coordinate3);
-                    node->addChild(lineSet);
-                }
-            };
+    struct VisualizerLine: TypedElementVisualizer<VisualizerLine, ElementLine, VisuDataLine>
+    {
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            data->lineStyle->lineWidth.setValue(element.lineWidth);
 
+            SbVec3f from(element.from.e0, element.from.e1, element.from.e2);
+            SbVec3f to(element.to.e0, element.to.e1, element.to.e2);
+            data->coordinate3->point.set1Value(0, from);
+            data->coordinate3->point.set1Value(1, to);
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerPose.h b/source/RobotAPI/components/ArViz/Coin/VisualizerPose.h
index 6701744558019dc33abc29aea8e19259a016710e..e8f7307d2add2c002da30466f8a5e3c9c6f55204 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerPose.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerPose.h
@@ -10,129 +10,147 @@
 #include <Inventor/nodes/SoTransform.h>
 #include <Inventor/nodes/SoTranslation.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataPose : TypedVisuData<SoSeparator>
     {
-        namespace coin
+        static const int NumberOfBlocks = 3;
+        VisuDataPose()
         {
+            auto* sep = node();
 
-            struct VisualizerPose: TypedElementVisualizer<VisualizerPose, ElementPose, SoSeparator>
+            for (int i = 0; i < 3; i++)
             {
-                void updateElement(ElementType const& element, NodeType* node)
+                SoTransform* t = new SoTransform();
+                SoMaterial* m = new SoMaterial();
+                t_[i] = t;
+                m_[i] = m;
+
+                SoCube* c = new SoCube();
+                SoCube* c2 = new SoCube();
+                SoTransform* t2 = new SoTransform();
+                c_[i] = c;
+                c2_[i] = c2;
+                t2_[i] = t2;
+
+                SoSeparator* tmp1 = new SoSeparator();
+                tmp1->addChild(m);
+                tmp1->addChild(t);
+                tmp1->addChild(c);
+                sep->addChild(tmp1);
+
+                SoSeparator* tmp2 = new SoSeparator();
+                SoMaterial* m2 = new SoMaterial();
+                m2->diffuseColor.setValue(1.0f, 1.0f, 1.0f);
+                tmp2->addChild(m2);
+
+                for (int j = 0; j < NumberOfBlocks; j++)
                 {
-                    std::string name = element.id;
-
-                    node->removeAllChildren();
-
-                    const float axisSize = 3.0f;
-                    const float axisLength = 100.0f;
-                    const int numberOfBlocks = 3;
-
-                    float scaling = element.scale;
-
-                    float blockSize = axisSize + 0.5f;
-                    float blockWidth = 0.1f;
-
-                    if (axisSize > 10.0f)
-                    {
-                        blockSize += axisSize / 10.0f;
-                        blockWidth += axisSize / 10.0f;
-                    }
-
-                    float axisBlockTranslation = axisLength / numberOfBlocks;
-
-                    for (int i = 0; i < 3; i++)
-                    {
-                        SoTransform* t = new SoTransform();
-                        SoMaterial* m = new SoMaterial();
-
-                        float translation = (axisLength / 2.0f + axisSize / 2.0f) * scaling;
-                        if (i == 0)
-                        {
-                            m->diffuseColor.setValue(1.0f, 0, 0);
-                            t->translation.setValue(translation, 0, 0);
-                        }
-                        else if (i == 1)
-                        {
-                            m->diffuseColor.setValue(0, 1.0f, 0);
-                            t->translation.setValue(0, translation, 0);
-                        }
-                        else
-                        {
-                            m->diffuseColor.setValue(0, 0, 1.0f);
-                            t->translation.setValue(0, 0, translation);
-                        }
-
-                        SoCube* c = new SoCube();
-                        SoCube* c2 = new SoCube();
-                        SoTransform* t2 = new SoTransform();
-
-                        if (i == 0)
-                        {
-                            c->width = axisLength * scaling;
-                            c->height = axisSize * scaling;
-                            c->depth = axisSize * scaling;
-                            c2->width = blockWidth * scaling;
-                            c2->height = blockSize * scaling;
-                            c2->depth = blockSize * scaling;
-                            t2->translation.setValue(axisBlockTranslation * scaling, 0, 0);
-                        }
-                        else if (i == 1)
-                        {
-                            c->height = axisLength * scaling;
-                            c->width = axisSize * scaling;
-                            c->depth = axisSize * scaling;
-                            c2->width = blockSize * scaling;
-                            c2->height = blockWidth * scaling;
-                            c2->depth = blockSize * scaling;
-                            t2->translation.setValue(0, axisBlockTranslation * scaling, 0);
-                        }
-                        else
-                        {
-                            c->depth = axisLength * scaling;
-                            c->height = axisSize * scaling;
-                            c->width = axisSize * scaling;
-                            c2->width = blockSize * scaling;
-                            c2->height = blockSize * scaling;
-                            c2->depth = blockWidth * scaling;
-                            t2->translation.setValue(0, 0, axisBlockTranslation * scaling);
-                        }
-
-                        SoSeparator* tmp1 = new SoSeparator();
-                        tmp1->addChild(m);
-                        tmp1->addChild(t);
-                        tmp1->addChild(c);
-                        node->addChild(tmp1);
-
-                        SoSeparator* tmp2 = new SoSeparator();
-                        SoMaterial* m2 = new SoMaterial();
-                        m2->diffuseColor.setValue(1.0f, 1.0f, 1.0f);
-                        tmp2->addChild(m2);
-
-                        for (int j = 0; j < numberOfBlocks; j++)
-                        {
-                            tmp2->addChild(t2);
-                            tmp2->addChild(c2);
-                        }
-
-                        node->addChild(tmp2);
-                    }
-
-                    SoSeparator* textSep = new SoSeparator();
-                    SoTranslation* moveT = new SoTranslation();
-                    moveT->translation.setValue(2.0f, 2.0f, 0.0f);
-                    textSep->addChild(moveT);
-                    SoAsciiText* textNode = new SoAsciiText();
-
-                    SbString text2(name.c_str());
-                    textNode->string.set(text2.getString());
-                    textSep->addChild(textNode);
-
-                    node->addChild(textSep);
+                    tmp2->addChild(t2);
+                    tmp2->addChild(c2);
                 }
-            };
 
+                sep->addChild(tmp2);
+            }
+
+            SoSeparator* textSep = new SoSeparator();
+            SoTranslation* moveT = new SoTranslation();
+            moveT->translation.setValue(2.0f, 2.0f, 0.0f);
+            textSep->addChild(moveT);
+            textNode = new SoAsciiText();
+            textSep->addChild(textNode);
+
+            sep->addChild(textSep);
+        }
+
+        SoAsciiText* textNode;
+        std::array<SoTransform*, 3> t_;
+        std::array<SoMaterial*, 3> m_;
+        std::array<SoCube*, 3> c_;
+        std::array<SoCube*, 3> c2_;
+        std::array<SoTransform*, 3> t2_;
+    };
+
+    struct VisualizerPose: TypedElementVisualizer<VisualizerPose, ElementPose, VisuDataPose>
+    {
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            const float axisSize = 3.0f;
+            const float axisLength = 100.0f;
+            const int numberOfBlocks = VisuDataPose::NumberOfBlocks;
+
+            float scaling = 1.0f;
+
+            float blockSize = axisSize + 0.5f;
+            float blockWidth = 0.1f;
+
+            if (axisSize > 10.0f)
+            {
+                blockSize += axisSize / 10.0f;
+                blockWidth += axisSize / 10.0f;
+            }
+
+            float axisBlockTranslation = axisLength / numberOfBlocks;
+
+            for (int i = 0; i < 3; i++)
+            {
+                SoTransform* t = data->t_[i];
+                SoMaterial* m = data->m_[i];
+
+                float translation = (axisLength / 2.0f + axisSize / 2.0f) * scaling;
+                if (i == 0)
+                {
+                    m->diffuseColor.setValue(1.0f, 0, 0);
+                    t->translation.setValue(translation, 0, 0);
+                }
+                else if (i == 1)
+                {
+                    m->diffuseColor.setValue(0, 1.0f, 0);
+                    t->translation.setValue(0, translation, 0);
+                }
+                else
+                {
+                    m->diffuseColor.setValue(0, 0, 1.0f);
+                    t->translation.setValue(0, 0, translation);
+                }
+
+                SoCube* c = data->c_[i];
+                SoCube* c2 = data->c2_[i];
+                SoTransform* t2 = data->t2_[i];
+
+                if (i == 0)
+                {
+                    c->width = axisLength * scaling;
+                    c->height = axisSize * scaling;
+                    c->depth = axisSize * scaling;
+                    c2->width = blockWidth * scaling;
+                    c2->height = blockSize * scaling;
+                    c2->depth = blockSize * scaling;
+                    t2->translation.setValue(axisBlockTranslation * scaling, 0, 0);
+                }
+                else if (i == 1)
+                {
+                    c->height = axisLength * scaling;
+                    c->width = axisSize * scaling;
+                    c->depth = axisSize * scaling;
+                    c2->width = blockSize * scaling;
+                    c2->height = blockWidth * scaling;
+                    c2->depth = blockSize * scaling;
+                    t2->translation.setValue(0, axisBlockTranslation * scaling, 0);
+                }
+                else
+                {
+                    c->depth = axisLength * scaling;
+                    c->height = axisSize * scaling;
+                    c->width = axisSize * scaling;
+                    c2->width = blockSize * scaling;
+                    c2->height = blockSize * scaling;
+                    c2->depth = blockWidth * scaling;
+                    t2->translation.setValue(0, 0, axisBlockTranslation * scaling);
+                }
+            }
+
+            data->textNode->string.setValue(element.id.c_str());
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerSphere.h b/source/RobotAPI/components/ArViz/Coin/VisualizerSphere.h
index 5c60b46e84397d40a38a340f903c80c3a65429ad..2320e0b39cdf062b4a7887a4ebba94c09ec4cd87 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerSphere.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerSphere.h
@@ -5,21 +5,20 @@
 #include <RobotAPI/interface/ArViz/Elements.h>
 #include <Inventor/nodes/SoSphere.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataSphere : TypedVisuData<SoSphere>
     {
-        namespace coin
-        {
 
-            struct VisualizerSphere: TypedElementVisualizer<VisualizerSphere, ElementSphere, SoSphere>
-            {
-                void updateElement(ElementType const& element, NodeType* node)
-                {
-                    node->radius = element.radius;
-                }
-            };
+    };
+
+    struct VisualizerSphere: TypedElementVisualizer<VisualizerSphere, ElementSphere, VisuDataSphere>
+    {
+        void updateElement(ElementType const& element, DataType* data)
+        {
+            auto* node = data->node();
 
+            node->radius = element.radius;
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizerText.h b/source/RobotAPI/components/ArViz/Coin/VisualizerText.h
index e942c78d5e40e577ae4716385ef8a1443f890b18..ee9df1f2f09ec0f9cf2ea1b52a7098cc7fc48d2d 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizerText.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizerText.h
@@ -6,19 +6,20 @@
 
 #include <Inventor/nodes/SoAsciiText.h>
 
-namespace armarx
+namespace armarx::viz::coin
 {
-    namespace viz
+    struct VisuDataText : TypedVisuData<SoAsciiText>
     {
-        namespace coin
+
+    };
+
+    struct VisualizerText: TypedElementVisualizer<VisualizerText, ElementText, VisuDataText>
+    {
+        void updateElement(ElementType const& element, DataType* data)
         {
-            struct VisualizerText: TypedElementVisualizer<VisualizerText, ElementText, SoAsciiText>
-            {
-                void updateElement(ElementType const& element, NodeType* node)
-                {
-                    node->string = element.text.c_str();
-                }
-            };
+            auto* node = data->node();
+
+            node->string = element.text.c_str();
         }
-    }
+    };
 }
diff --git a/source/RobotAPI/components/ArVizExample/ArVizExample.cpp b/source/RobotAPI/components/ArVizExample/ArVizExample.cpp
index 8d02e7bc76f9d0f30fe26542111ada6cc0f9d407..3432c156b4e70b9a1f2cb610428b12a703e436d8 100644
--- a/source/RobotAPI/components/ArVizExample/ArVizExample.cpp
+++ b/source/RobotAPI/components/ArVizExample/ArVizExample.cpp
@@ -182,6 +182,24 @@ void ArVizExample::update()
 
             layer.elements.push_back(arrow);
         }
+        {
+            viz::ElementArrowCirclePtr circle(new viz::ElementArrowCircle);
+            circle->id = "circle";
+            circle->action = viz::Element_UPDATE;
+
+            float modTime = std::fmod(timeInSeconds, 2.0 * M_PI);
+            circle->completion = std::sin(modTime);
+
+            circle->radius = 100.0f;
+            circle->width = 10.0f;
+
+            Eigen::Vector3f pos = Eigen::Vector3f::Zero();
+            pos.z() = +300.0f;
+            circle->pose = makeGlobalPose(pos, Eigen::Quaternionf::Identity());
+            circle->color = armarx::viz::Color{255, 255, 0, 255};
+
+            layer.elements.push_back(circle);
+        }
 
         topic->updateLayers({layer});