From bc942044e251a0f6aebaf3791d5342f4f4e33966 Mon Sep 17 00:00:00 2001
From: Mirko Waechter <mirko.waechter@kit.edu>
Date: Wed, 18 May 2016 17:53:33 +0200
Subject: [PATCH] kinematic simulation can now deal with continuous joints

---
 .../units/KinematicUnitSimulation.cpp         | 43 ++++++++++++++-----
 .../units/KinematicUnitSimulation.h           |  4 ++
 2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/source/RobotAPI/components/units/KinematicUnitSimulation.cpp b/source/RobotAPI/components/units/KinematicUnitSimulation.cpp
index 5b81f9c98..978fedcf5 100644
--- a/source/RobotAPI/components/units/KinematicUnitSimulation.cpp
+++ b/source/RobotAPI/components/units/KinematicUnitSimulation.cpp
@@ -119,7 +119,7 @@ void KinematicUnitSimulation::simulationFunction()
         {
 
             float newAngle = 0.0f;
-
+            KinematicUnitSimulationJointInfo& jointInfo = jointInfos[it->first];
             // calculate joint positions if joint is in velocity control mode
             if (it->second.controlMode == eVelocityControl)
             {
@@ -152,11 +152,14 @@ void KinematicUnitSimulation::simulationFunction()
             }
 
             // constrain the angle
-            KinematicUnitSimulationJointInfo& jointInfo = jointInfos[it->first];
-            float maxAngle = (jointInfo.hasLimits()) ? jointInfo.limitHi : 2.0 * M_PI;
-            float minAngle = (jointInfo.hasLimits()) ? jointInfo.limitLo : -2.0 * M_PI;
-            newAngle = std::max<float>(newAngle, minAngle);
-            newAngle = std::min<float>(newAngle, maxAngle);
+            if (!jointInfo.continuousJoint())
+            {
+                float maxAngle = (jointInfo.hasLimits()) ? jointInfo.limitHi : M_PI;
+                float minAngle = (jointInfo.hasLimits()) ? jointInfo.limitLo : -M_PI;
+
+                newAngle = std::max<float>(newAngle, minAngle);
+                newAngle = std::min<float>(newAngle, maxAngle);
+            }
 
             // Check if joint existed before
             KinematicUnitSimulationJointStates::iterator itPrev = previousJointStates.find(it->first);
@@ -180,6 +183,18 @@ void KinematicUnitSimulation::simulationFunction()
                 aVelValueChanged = true;
             }
 
+            if (jointInfo.continuousJoint())
+            {
+                if (newAngle < 0)
+                {
+                    newAngle = fmod(newAngle - M_PI, 2 * M_PI) + M_PI;
+                }
+                else
+                {
+                    newAngle = fmod(newAngle + M_PI, 2 * M_PI) - M_PI;
+                }
+
+            }
 
             actualJointAngles[it->first] = newAngle;
             actualJointVelocities[it->first] = it->second.velocity;
@@ -252,11 +267,11 @@ void KinematicUnitSimulation::setJointAngles(const NameValueMap& targetJointAngl
             {
                 aValueChanged = true;
             }
-
-            if (jointInfos[targetJointName].hasLimits())
+            KinematicUnitSimulationJointInfo& jointInfo = jointInfos[targetJointName];
+            if (jointInfo.hasLimits() && !jointInfo.continuousJoint())
             {
-                targetJointAngle = std::max<float>(targetJointAngle, jointInfos[targetJointName].limitLo);
-                targetJointAngle = std::min<float>(targetJointAngle, jointInfos[targetJointName].limitHi);
+                targetJointAngle = std::max<float>(targetJointAngle, jointInfo.limitLo);
+                targetJointAngle = std::min<float>(targetJointAngle, jointInfo.limitHi);
             }
 
             if (!usePDControllerForPosMode)
@@ -270,8 +285,16 @@ void KinematicUnitSimulation::setJointAngles(const NameValueMap& targetJointAngl
                 if (pid)
                 {
                     pid->reset();
+                    if (jointInfo.continuousJoint())
+                    {
+                        float delta = targetJointAngle - iterJoints->second.angle;
+                        float signedSmallestDelta = atan2(sin(delta), cos(delta));
+                        targetJointAngle = iterJoints->second.angle + signedSmallestDelta;
+                    }
+
                     pid->setTarget(targetJointAngle);
 
+
                 }
             }
         }
diff --git a/source/RobotAPI/components/units/KinematicUnitSimulation.h b/source/RobotAPI/components/units/KinematicUnitSimulation.h
index 4b730a0f4..87cea5bde 100644
--- a/source/RobotAPI/components/units/KinematicUnitSimulation.h
+++ b/source/RobotAPI/components/units/KinematicUnitSimulation.h
@@ -94,6 +94,10 @@ namespace armarx
         {
             return (limitLo != limitHi);
         }
+        bool continuousJoint() const
+        {
+            return !hasLimits() || limitLo - limitHi >= 360.0f;
+        }
 
         float limitLo;
         float limitHi;
-- 
GitLab