diff --git a/VirtualRobot/Nodes/HemisphereJoint/Joint.cpp b/VirtualRobot/Nodes/HemisphereJoint/Joint.cpp
index 6cfdd31f6308864540f2cc4f13a2056d832bc4d3..6eabfa7f98e69d5bdb841c8072a676d545d6b70e 100644
--- a/VirtualRobot/Nodes/HemisphereJoint/Joint.cpp
+++ b/VirtualRobot/Nodes/HemisphereJoint/Joint.cpp
@@ -46,6 +46,13 @@ namespace VirtualRobot::hemisphere
         };
     }
 
+    Eigen::Vector3d Joint::getCorrectedEndEffectorTranslation() const
+    {
+        Eigen::Vector3d translation = getEndEffectorTranslation();
+        translation = translation.normalized() * radius;
+        return translation;
+    }
+
 
     Eigen::Matrix3d Joint::getEndEffectorRotation() const
     {
diff --git a/VirtualRobot/Nodes/HemisphereJoint/Joint.h b/VirtualRobot/Nodes/HemisphereJoint/Joint.h
index f9a8bcf4eeda9030231580d238a9ad54a8db6c94..e2b8fb8b17ba385cd2718cd3890d8e1e0fa4e22b 100644
--- a/VirtualRobot/Nodes/HemisphereJoint/Joint.h
+++ b/VirtualRobot/Nodes/HemisphereJoint/Joint.h
@@ -27,6 +27,7 @@ namespace VirtualRobot::hemisphere
 
 
         Eigen::Vector3d getEndEffectorTranslation() const;
+        Eigen::Vector3d getCorrectedEndEffectorTranslation() const;
         Eigen::Matrix3d getEndEffectorRotation() const;
         Eigen::Matrix4d getEndEffectorTransform() const;
         Jacobian getJacobian() const;
diff --git a/VirtualRobot/Nodes/RobotNodeHemisphere.cpp b/VirtualRobot/Nodes/RobotNodeHemisphere.cpp
index f824e9d437c41f17b32a003d0aee83672c4a1f5b..9b05217244099de29e3f146bb85ec43d01ac7de9 100644
--- a/VirtualRobot/Nodes/RobotNodeHemisphere.cpp
+++ b/VirtualRobot/Nodes/RobotNodeHemisphere.cpp
@@ -9,6 +9,7 @@
 #include <Eigen/Geometry>
 
 #include <SimoxUtility/math/pose/pose.h>
+#include <SimoxUtility/meta/enum/EnumNames.hpp>
 
 
 namespace VirtualRobot
@@ -16,11 +17,21 @@ namespace VirtualRobot
 
     static const float limit = 1.0;
 
+    extern const simox::meta::EnumNames<RobotNodeHemisphere::Role> RoleNames =
+    {
+        { RobotNodeHemisphere::Role::FIRST, "first" },
+        { RobotNodeHemisphere::Role::SECOND, "second" },
+    };
 
     VirtualRobot::RobotNodeHemisphere::RobotNodeHemisphere()
     {
     }
 
+    RobotNodeHemisphere::Role RobotNodeHemisphere::RoleFromString(const std::string& string)
+    {
+        return RoleNames.from_name(string);
+    }
+
     RobotNodeHemisphere::RobotNodeHemisphere(
             RobotWeakPtr rob,
             const std::string& name,
@@ -33,8 +44,7 @@ namespace VirtualRobot
             float jointValueOffset,
             const SceneObject::Physics& physics,
             CollisionCheckerPtr colChecker,
-            RobotNodeType type,
-            bool isTail
+            RobotNodeType type
             ) :
         RobotNode(rob, name, -limit, limit, visualization, collisionModel,
                   jointValueOffset, physics, colChecker, type)
@@ -42,15 +52,6 @@ namespace VirtualRobot
         (void) axis;
         (void) jointLimitLo, (void) jointLimitHi;
 
-        if (isTail)
-        {
-            tail.emplace(Tail{});
-        }
-        else
-        {
-            head.emplace(Head{});
-        }
-
         initialized = false;
         optionalDHParameter.isSet = false;
         localTransformation = preJointTransform;
@@ -72,8 +73,7 @@ namespace VirtualRobot
             RobotNodeType type
             ) :
         RobotNode(rob, name, jointLimitLo, jointLimitHi, visualization, collisionModel,
-                  jointValueOffset, physics, colChecker, type),
-        tail(Tail{})
+                  jointValueOffset, physics, colChecker, type)
     {
         initialized = false;
         optionalDHParameter.isSet = true;
@@ -103,83 +103,91 @@ namespace VirtualRobot
     }
 
 
-    RobotNodeHemispherePtr RobotNodeHemisphere::MakeHead(
-            RobotWeakPtr robot, const std::string& name, RobotNodeType type)
-    {
-        bool isTail = false;
-        return std::make_shared<RobotNodeHemisphere>(
-                    robot, name, -limit, limit,
-                    Eigen::Matrix4f::Identity(), Eigen::Vector3f::Zero(),
-                    nullptr, nullptr, 0.0, Physics{}, nullptr, type,
-                    isTail);
-    }
-
-
     RobotNodeHemisphere::~RobotNodeHemisphere()
     = default;
 
 
+    void RobotNodeHemisphere::setXmlInfo(const XmlInfo& info)
+    {
+        VR_ASSERT(second.has_value());
+        switch (info.role)
+        {
+        case Role::FIRST:
+            first.emplace(First{});
+            first->math.joint.setConstants(info.lever, info.theta0);
+            break;
+
+        case Role::SECOND:
+            second.emplace(Second{});
+            break;
+        }
+    }
+
+
     bool RobotNodeHemisphere::initialize(
             SceneObjectPtr parent,
-            const std::vector<SceneObjectPtr>& _children)
+            const std::vector<SceneObjectPtr>& children)
     {
-        (void) _children;
-        VR_ASSERT_MESSAGE(head xor sub, head.has_value() << " / " sub.has_value());
+        VR_ASSERT_MESSAGE(first xor sub, first.has_value() << " / " sub.has_value());
 
-        if (tail)
+        // The second node needs to store a reference to the first node.
+        if (second)
         {
-            if (not tail->head)
+            VR_ASSERT_MESSAGE(not second->first, "Second must not be initialized yet.");
+
+            RobotNodeHemisphere* firstNode = dynamic_cast<RobotNodeHemisphere*>(parent.get());
+            RobotNodeHemisphere* secondNode = this;
+
+            if (not (firstNode and firstNode->first))
             {
-                // Create a head joint as a child of parent.
-                RobotNodeHemispherePtr headNode = RobotNodeHemisphere::MakeHead(
-                            robot, name + "_head", nodeType
-                            );
-
-                // Move robot node up parameters.
-                {
-                    headNode->setLocalTransformation(this->localTransformation);
-                    this->localTransformation.setIdentity();
-                }
-
-                // Set robot node up parameters.
-                {
-                    const hemisphere::Joint& joint = tail->joint;
-
-                    // (actuator + offset) must be in [-1, 1]
-                    // => low: actuator = -1 - offset
-                    // => hi: actuator = 1 - offset
-                    double lo = -1 - joint.actuatorOffset;
-                    double hi = +1 - joint.actuatorOffset;
-
-                    this->jointLimitLo = lo;
-                    headNode->jointLimitLo = lo;
-
-                    this->jointLimitHi = hi;
-                    headNode->jointLimitHi = hi;
-                }
-
-                // Start:  parent -> tail
-                // Goal:   parent -> head -> tail
-                SceneObjectPtr tailNode = shared_from_this();
-                parent->detachChild(tailNode);
-                headNode->attachChild(tailNode);
-                parent->attachChild(headNode);
-
-                tail->head = headNode;
-
-                headNode->initialize(parent, {tailNode});
-                // Stop here, recurse when the head node initializes this node (its child).
-                return true;
+                std::stringstream ss;
+                ss << "The parent of a hemisphere joint with role '" << RoleNames.to_name(Role::SECOND) << "' "
+                   << "must have be a hemisphere joint with role '" << RoleNames.to_name(Role::FIRST) << "' ";
+                THROW_VR_EXCEPTION(ss.str());
             }
-            else
+
+            // Save pointer to firstNode
+            second->first = firstNode;
+
+            // Set up robot node parameters.
             {
-                // Recurse.
-                return RobotNode::initialize(parent, children);
+                const hemisphere::Joint& joint = second->math().joint;
+
+                // (actuator + offset) must be in [-1, 1]
+                // => low: actuator = -1 - offset
+                // => hi: actuator = 1 - offset
+                double lo = -1 - joint.actuatorOffset;
+                double hi = +1 - joint.actuatorOffset;
+
+                firstNode->jointLimitLo = lo;
+                secondNode->jointLimitLo = lo;
+
+                firstNode->jointLimitHi = hi;
+                secondNode->jointLimitHi = hi;
             }
         }
-        else
+
+        return RobotNode::initialize(parent, children);
+    }
+
+
+    void RobotNodeHemisphere::JointMath::update(const Eigen::Vector2f& actuators)
+    {
+        const double maxNorm = 1;
+
+        if (actuators != this->actuators)
         {
-            return RobotNode::initialize(parent, children);
+            Eigen::Vector2f a = actuators;
+            a = a.array() + joint.actuatorOffset;
+
+            double norm = a.norm();
+            if (norm > maxNorm)
+            {
+                a *= (maxNorm / norm);
+            }
+
+            this->actuators = actuators;
+            joint.computeFK(a(0), a(1));
         }
     }
 
@@ -187,47 +195,43 @@ namespace VirtualRobot
     void RobotNodeHemisphere::updateTransformationMatrices(
             const Eigen::Matrix4f& parentPose)
     {
-        VR_ASSERT_MESSAGE(head xor sub, head.has_value() << " / " sub.has_value());
+        VR_ASSERT_MESSAGE(first xor sub, first.has_value() << " / " sub.has_value());
 
-        const double maxNorm = 1;
-
-        if (head)
+        if (first)
         {
             globalPose = parentPose * localTransformation;
         }
-        else if (tail)
+        else if (second)
         {
-            Eigen::Vector2d a(tail->head->getJointValue(), this->getJointValue());
-            a = a.array() + tail->joint.actuatorOffset;
+            VR_ASSERT_MESSAGE(second->first, "First node must be known to second node.");
 
-            double norm = a.norm();
-            if (norm > maxNorm)
-            {
-                a *= (maxNorm / norm);
-            }
+            JointMath& math = second->math();
+            Eigen::Vector2f actuators(second->first->getJointValue(), this->getJointValue());
 
-            tail->joint.computeFK(a(0), a(1));
+            math.update(actuators);
 
-            Eigen::Vector3d translation = tail->joint.getEndEffectorTranslation();
-            translation = translation.normalized() * tail->joint.radius;
-            const Eigen::Matrix3d rotation = tail->joint.getEndEffectorRotation();
+            Eigen::Vector3d translation = math.joint.getCorrectedEndEffectorTranslation();
+            const Eigen::Matrix3d rotation = math.joint.getEndEffectorRotation();
             const Eigen::Matrix4d transform = simox::math::pose(translation, rotation);
 
-            globalPose = parentPose * localTransformation * transform.cast<float>();
-
-            Eigen::IOFormat iof(5, 0, " ", "\n", "    [", "]");
-            std::cout << __FUNCTION__ << "() with "
-                      << "\n  lever = " << tail->joint.lever
-                      << "\n  theta0 = " << tail->joint.theta0
-                      << "\n  radius = " << tail->joint.radius
-                      << "\n  actuator offset = " << tail->joint.actuatorOffset
-                      << "\n  joint value = " << jointValue
-                      << "\n  joint value offset = " << jointValueOffset
-                      << "\n  actuator = \n" << a.transpose().format(iof)
-                      << "\n  actuator + offset = \n" << (a.array() + tail->joint.actuatorOffset).transpose().format(iof)
-                      << "\n  local transform = \n" << localTransformation.format(iof)
-                      << "\n  transform = \n" << transform.format(iof)
-                      << std::endl;
+            // Update Second
+            {
+                this->globalPose = parentPose * localTransformation * transform.cast<float>();
+
+                Eigen::IOFormat iof(5, 0, " ", "\n", "    [", "]");
+                std::cout << __FUNCTION__ << "() of second actuator with "
+                          << "\n  lever = " << math.joint.lever
+                          << "\n  theta0 = " << math.joint.theta0
+                          << "\n  radius = " << math.joint.radius
+                          << "\n  actuator offset = " << math.joint.actuatorOffset
+                          << "\n  joint value = " << jointValue
+                          << "\n  joint value offset = " << jointValueOffset
+                          << "\n  actuator = \n" << actuators.transpose().format(iof)
+                          << "\n  actuator + offset = \n" << (actuators.array() + math.joint.actuatorOffset).transpose().format(iof)
+                          << "\n  local transform = \n" << localTransformation.format(iof)
+                          << "\n  joint transform = \n" << transform.format(iof)
+                          << std::endl;
+            }
         }
     }
 
@@ -235,7 +239,7 @@ namespace VirtualRobot
     void RobotNodeHemisphere::print(bool printChildren, bool printDecoration) const
     {
         ReadLockPtr lock = getRobot()->getReadLock();
-        VR_ASSERT_MESSAGE(head xor sub, head.has_value() << " / " sub.has_value());
+        VR_ASSERT_MESSAGE(first xor sub, first.has_value() << " / " sub.has_value());
 
         if (printDecoration)
         {
@@ -244,14 +248,14 @@ namespace VirtualRobot
 
         RobotNode::print(false, false);
 
-        if (head)
+        if (first)
         {
-            std::cout << "* Hemisphere joint head node";
+            std::cout << "* Hemisphere joint first node";
         }
-        else if (tail)
+        else if (second)
         {
-            std::cout << "* Hemisphere joint tail node";
-            std::cout << "* Transform: \n" << tail->joint.getEndEffectorTransform() << std::endl;
+            std::cout << "* Hemisphere joint second node";
+            std::cout << "* Transform: \n" << second->math().joint.getEndEffectorTransform() << std::endl;
         }
 
         if (printDecoration)
@@ -306,11 +310,6 @@ namespace VirtualRobot
         return true;
     }
 
-    void RobotNodeHemisphere::setConstants(double lever, double theta0)
-    {
-        VR_ASSERT(tail);
-        tail->joint.setConstants(lever, theta0);
-    }
 
     void RobotNodeHemisphere::checkValidRobotNodeType()
     {
@@ -321,18 +320,20 @@ namespace VirtualRobot
 
     std::string RobotNodeHemisphere::_toXML(const std::string& /*modelPath*/)
     {
-        VR_ASSERT_MESSAGE(head xor sub, head.has_value() << " / " sub.has_value());
+        VR_ASSERT_MESSAGE(first xor sub, first.has_value() << " / " sub.has_value());
 
-        if (head)
+        if (first)
         {
-            // Hidden, not part of xml.
+            // TODO
             return "";
         }
         else
         {
+            JointMath& math = second->math();
+
             std::stringstream ss;
             ss << "\t\t<Joint type='Hemisphere'>" << std::endl;
-            ss << "\t\t\t<hemisphere lever='" << tail->joint.lever << "' theta0='" << tail->joint.theta0 << "' />" << std::endl;
+            ss << "\t\t\t<hemisphere lever='" << math.joint.lever << "' theta0='" << math.joint.theta0 << "' />" << std::endl;
             ss << "\t\t\t<limits lo='" << jointLimitLo << "' hi='" << jointLimitHi << "' units='radian'/>" << std::endl;
             ss << "\t\t\t<MaxAcceleration value='" << maxAcceleration << "'/>" << std::endl;
             ss << "\t\t\t<MaxVelocity value='" << maxVelocity << "'/>" << std::endl;
@@ -350,7 +351,6 @@ namespace VirtualRobot
         }
     }
 
-
     float RobotNodeHemisphere::getLMTC(float angle)
     {
         return std::sqrt(2 - 2 * std::cos(angle));
@@ -363,4 +363,6 @@ namespace VirtualRobot
         return std::sqrt(4 * std::pow(b, 2) - std::pow(b, 4)) / (2 * b);
     }
 
+
+
 }
diff --git a/VirtualRobot/Nodes/RobotNodeHemisphere.h b/VirtualRobot/Nodes/RobotNodeHemisphere.h
index 74ca0a1d37d27ce27869802a5aff9c8fc9056189..15904d36e6dc1baa4dd523789029b5c8c93bb5da 100644
--- a/VirtualRobot/Nodes/RobotNodeHemisphere.h
+++ b/VirtualRobot/Nodes/RobotNodeHemisphere.h
@@ -41,6 +41,22 @@ namespace VirtualRobot
     {
     public:
 
+        enum class Role
+        {
+            FIRST,
+            SECOND,
+        };
+        static Role RoleFromString(const std::string& string);
+
+        struct XmlInfo
+        {
+            Role role;
+
+            // Only set for first:
+            double theta0 = -1;
+            double lever = -1;
+        };
+
         friend class RobotFactory;
 
         EIGEN_MAKE_ALIGNED_OPERATOR_NEW
@@ -58,8 +74,7 @@ namespace VirtualRobot
                 float jointValueOffset = 0.0f,                      ///< An offset that is internally added to the joint value
                 const SceneObject::Physics& p = {},                 ///< physics information
                 CollisionCheckerPtr colChecker = nullptr,           ///< A collision checker instance (if not set, the global col checker is used)
-                RobotNodeType type = Generic,
-                bool isTail = true
+                RobotNodeType type = Generic
                 );
 
         RobotNodeHemisphere(
@@ -84,6 +99,8 @@ namespace VirtualRobot
         ~RobotNodeHemisphere() override;
 
 
+        void setXmlInfo(const XmlInfo& info);
+
         bool
         initialize(
                 SceneObjectPtr parent = nullptr,
@@ -100,8 +117,6 @@ namespace VirtualRobot
         bool
         isHemisphereJoint() const override;
 
-        void setConstants(double lever, double theta0);
-
         /**
          * \brief getLMTC Calculates the spatial distance between the parent of a Hemisphere joint
          * and a given child with the joint set to a given angle (e.g. the length of a
@@ -131,15 +146,6 @@ namespace VirtualRobot
 
         RobotNodeHemisphere();
 
-        // Head node constructor.
-        static RobotNodeHemispherePtr MakeHead(
-                RobotWeakPtr robot,
-                const std::string& name,
-                RobotNodeType type = Generic
-                );
-
-
-
         /// Derived classes add custom XML tags here
         std::string
         _toXML(
@@ -168,20 +174,37 @@ namespace VirtualRobot
 
     protected:
 
-        struct Head
+        struct JointMath
         {
+            /// The actuator values that were used to compute the joint math.
+            Eigen::Vector2f actuators = Eigen::Vector2f::Constant(std::numeric_limits<float>::min());
+            /// The joint math.
+            hemisphere::Joint joint;
+
+            void update(const Eigen::Vector2f& actuators);
         };
-        std::optional<Head> head;
 
-        struct Tail
+        struct First
         {
-            /// The second actuator node.
-            RobotNodeHemispherePtr head = nullptr;
+            JointMath math;
+        };
+        std::optional<First> first;
 
-            /// The joint math.
-            hemisphere::Joint joint;
+        struct Second
+        {
+            /// The first actuator node.
+            RobotNodeHemisphere* first = nullptr;
+
+            JointMath& math()
+            {
+                return first->first->math;
+            }
+            const JointMath& math() const
+            {
+                return first->first->math;
+            }
         };
-        std::optional<Tail> tail;
+        std::optional<Second> second;
 
     };
 
diff --git a/VirtualRobot/XML/RobotIO.cpp b/VirtualRobot/XML/RobotIO.cpp
index 5d95620dc11d027df71806d721a6398a7cd4f69f..023244cea72a650c1f6f04a7b922878355b85155 100644
--- a/VirtualRobot/XML/RobotIO.cpp
+++ b/VirtualRobot/XML/RobotIO.cpp
@@ -24,6 +24,7 @@
 #include <SimoxUtility/xml/rapidxml/rapidxml_print.hpp>
 #include <SimoxUtility/filesystem/remove_trailing_separator.h>
 #include <SimoxUtility/math/convert/deg_to_rad.h>
+#include <SimoxUtility/algorithm/string/string_tools.h>
 
 #include <vector>
 #include <fstream>
@@ -249,12 +250,7 @@ namespace VirtualRobot
         bool scaleVisu = false;
         Eigen::Vector3f scaleVisuFactor = Eigen::Vector3f::Zero();
 
-        struct Hemisphere
-        {
-            float lever;
-            float theta0;
-        };
-        std::optional<Hemisphere> hemisphere;
+        std::optional<RobotNodeHemisphere::XmlInfo> hemisphere;
 
         while (node)
         {
@@ -454,10 +450,28 @@ namespace VirtualRobot
             }
             else if (nodeName == "hemisphere")
             {
-                hemisphere = Hemisphere {
-                        .lever = getFloatByAttributeName(node, "lever"),
-                        .theta0 = simox::math::deg_to_rad(getFloatByAttributeName(node, "theta0")),
-                };
+                hemisphere.emplace();
+
+                std::string roleString = processStringAttribute("role", node, true);
+                roleString = simox::alg::to_lower(roleString);
+                try
+                {
+                    hemisphere->role = RobotNodeHemisphere::RoleFromString(roleString);
+                }
+                catch (const std::out_of_range& e)
+                {
+                    THROW_VR_EXCEPTION("Invalid role in hemisphere joint: " << e.what())
+                }
+
+                switch (hemisphere->role)
+                {
+                case RobotNodeHemisphere::Role::FIRST:
+                    hemisphere->lever = getFloatByAttributeName(node, "lever");
+                    hemisphere->theta0 = simox::math::deg_to_rad(getFloatByAttributeName(node, "theta0"));
+                    break;
+                case RobotNodeHemisphere::Role::SECOND:
+                    break;
+                }
             }
             else
             {
@@ -570,7 +584,7 @@ namespace VirtualRobot
         if (robotNode->isHemisphereJoint() and hemisphere.has_value())
         {
             RobotNodeHemispherePtr node = std::dynamic_pointer_cast<RobotNodeHemisphere>(robotNode);
-            node->setConstants(hemisphere->lever, hemisphere->theta0);
+            node->setXmlInfo(hemisphere.value());
         }
 
         if (scaleVisu)
diff --git a/VirtualRobot/data/robots/examples/HemisphereJoint/Joint3Hemisphere.xml b/VirtualRobot/data/robots/examples/HemisphereJoint/Joint3Hemisphere.xml
index 9f402bb7b9df186406f9b0519aec56e1b2f32713..7cdabb74a2d65856611b5a7f909a84ea42811026 100644
--- a/VirtualRobot/data/robots/examples/HemisphereJoint/Joint3Hemisphere.xml
+++ b/VirtualRobot/data/robots/examples/HemisphereJoint/Joint3Hemisphere.xml
@@ -1,16 +1,16 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 
-<Robot Type="Simple3DoFRobotWithHemisphereJoint" StandardName="Simple3DoFRobotWithHemisphereJoint" RootNode="Start">
+<Robot Type="Simple3DoFRobotWithHemisphereJoint" StandardName="Simple3DoFRobotWithHemisphereJoint" RootNode="First">
 	
-	<RobotNode name="Start">
+    <RobotNode name="First">
         <Visualization enable="true">
 			<CoordinateAxis enable="true" scaling="1" text="Root"/>
             <File type="Inventor">end.iv</File>
 		</Visualization>
-		<Child name="Joint1"/>
+        <Child name="Joint1_Revolute"/>
 	</RobotNode>
 
-	<RobotNode name="Joint1">
+    <RobotNode name="Joint1_Revolute">
 		<Joint type="revolute">
 			<Limits unit="degree" lo="-90" hi="90"/>
             <Axis x="1" y="0" z="0"/>
@@ -19,24 +19,35 @@
              <File type="Inventor">joint_01_base.iv</File>
 			 <UseAsCollisionModel/>
 		</Visualization>
-        <Child name="Joint2Hemisphere"/>
+        <Child name="Joint2_Hemisphere_A"/>
 	</RobotNode>
 
-    <RobotNode name="Joint2Hemisphere">
+    <RobotNode name="Joint2_Hemisphere_A">
         <Transform>
             <Translation x="0" y="0" z="300" />
         </Transform>
         <Joint type="hemisphere">
-            <hemisphere lever="40" theta0="25" />
+            <hemisphere role="first" lever="40" theta0="25" />
         </Joint>
         <Visualization enable="true">
-             <File type="Inventor">joint_02_hemisphere.iv</File>
+             <File type="Inventor">joint_02_hemisphere_a.iv</File>
 			 <UseAsCollisionModel/>
         </Visualization>
-        <Child name="Joint3"/>
+        <Child name="Joint2_Hemisphere_B"/>
 	</RobotNode>
 
-    <RobotNode name="Joint3">
+    <RobotNode name="Joint2_Hemisphere_B">
+        <Joint type="hemisphere">
+            <hemisphere role="second" />
+        </Joint>
+        <Visualization enable="true">
+             <File type="Inventor">joint_02_hemisphere_b.iv</File>
+             <UseAsCollisionModel/>
+        </Visualization>
+        <Child name="Joint3_Revolute"/>
+    </RobotNode>
+
+    <RobotNode name="Joint3_Revolute">
 		<Transform>
             <Translation x="0" y="0" z="50" />
 		</Transform>
@@ -48,10 +59,10 @@
              <File type="Inventor">joint_03_finger.iv</File>
 			 <UseAsCollisionModel/>
 		</Visualization>
-		<Child name="EndPoint"/>
+        <Child name="Last"/>
 	</RobotNode>
 
-	<RobotNode name="EndPoint">
+    <RobotNode name="Last">
 		<Transform>
             <Translation x="0" y="0" z="300" />
 		</Transform>
@@ -61,17 +72,20 @@
 		</Visualization>
 	</RobotNode>
 
-	<RobotNodeSet name="AllJoints" kinematicRoot="Joint1">
-		<Node name="Joint1"/>
-        <Node name="Joint2Hemisphere"/>
-        <Node name="Joint3"/>
+    <RobotNodeSet name="AllJoints" kinematicRoot="Joint1_Revolute">
+        <Node name="Joint1_Revolute"/>
+        <Node name="Joint2_Hemisphere_A"/>
+        <Node name="Joint2_Hemisphere_B"/>
+        <Node name="Joint3_Revolute"/>
 	</RobotNodeSet>
 
 	<RobotNodeSet name="CollisionModel">
-		<Node name="Joint1"/>
-        <Node name="Joint2Hemisphere"/>
-        <Node name="Joint3"/>
-  	<Node name="EndPoint"/>
+        <Node name="First"/>
+        <Node name="Joint1_Revolute"/>
+        <Node name="Joint2_Hemisphere_A"/>
+        <Node name="Joint2_Hemisphere_B"/>
+        <Node name="Joint3_Revolute"/>
+        <Node name="Last"/>
 	</RobotNodeSet>
 
 </Robot>
diff --git a/VirtualRobot/data/robots/examples/HemisphereJoint/joint_01_base.iv b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_01_base.iv
index 1ed4911cf36b9915d2781608b264b20f3fa7a691..c6a9a936f3d197fc11a51646da9bbf086c47f71b 100644
--- a/VirtualRobot/data/robots/examples/HemisphereJoint/joint_01_base.iv
+++ b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_01_base.iv
@@ -31,10 +31,6 @@ Separator {
     Translation {
         translation 0 150 0
     }
-    Sphere
-    {
-        radius 16.90475
-    }
     Cube
     {
         width 60
diff --git a/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_a.iv b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_a.iv
new file mode 100644
index 0000000000000000000000000000000000000000..e65631a950c15eb9051b713c8ab4a42c51f2b034
--- /dev/null
+++ b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_a.iv
@@ -0,0 +1,15 @@
+#Inventor V2.0 ascii
+
+Separator {
+    
+    Units {
+        units MILLIMETERS
+    }
+    Material {
+        diffuseColor .5 .5 1
+    }
+    Sphere
+    {
+        radius 16.90475
+    }
+}
diff --git a/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere.iv b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_b.iv
similarity index 69%
rename from VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere.iv
rename to VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_b.iv
index 9f3a88e2ef6d595ef2bc83c3e0a41adaad384d03..e80f74c3c49b075d675cde5b4337dec56de8605e 100644
--- a/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere.iv
+++ b/VirtualRobot/data/robots/examples/HemisphereJoint/joint_02_hemisphere_b.iv
@@ -1,26 +1,33 @@
 #Inventor V2.0 ascii
 
-Separator {
+Separator
+{
     
-    Units {
+    Units
+    {
         units MILLIMETERS
     }
-    Material {
+        Material {
         diffuseColor .5 1 .5
     }
-    Sphere {
+
+    Rotation
+    {
+        rotation 1 0 0  1.57
+    }
+    Sphere
+    {
         radius 16.90475
     }
     Cube
     {
         width 60
-        height 60
-        depth 1
+        height 1
+        depth 60
     }
-    Rotation {
-        rotation 1 0 0  1.57
-    }
-    Translation {
+
+    Translation
+    {
         translation 0 25 0
     }
     Cylinder {
@@ -28,4 +35,5 @@ Separator {
         height 50
         parts (SIDES | TOP | BOTTOM)
     }
+
 }