From 765adaf494e236c42f98b72518a6e6424ebb2272 Mon Sep 17 00:00:00 2001
From: Markus <Markus.Przybylski@kit.edu>
Date: Thu, 23 Jan 2014 11:56:51 +0100
Subject: [PATCH] Added statechart that closes the robot hand by setting
 predefined torques to the finger joints.

---
 source/RobotAPI/CMakeLists.txt                |   2 +-
 .../GraspingWithTorques/CMakeLists.txt        |  31 ++
 .../GraspingWithTorques.cpp                   | 294 ++++++++++++++++++
 .../GraspingWithTorques/GraspingWithTorques.h | 114 +++++++
 4 files changed, 440 insertions(+), 1 deletion(-)
 create mode 100644 source/RobotAPI/GraspingWithTorques/CMakeLists.txt
 create mode 100644 source/RobotAPI/GraspingWithTorques/GraspingWithTorques.cpp
 create mode 100644 source/RobotAPI/GraspingWithTorques/GraspingWithTorques.h

diff --git a/source/RobotAPI/CMakeLists.txt b/source/RobotAPI/CMakeLists.txt
index 475cc9398..da048e516 100644
--- a/source/RobotAPI/CMakeLists.txt
+++ b/source/RobotAPI/CMakeLists.txt
@@ -2,4 +2,4 @@ add_subdirectory(core)
 add_subdirectory(motioncontrol)
 add_subdirectory(applications)
 add_subdirectory(units)
-
+add_subdirectory(GraspingWithTorques)
diff --git a/source/RobotAPI/GraspingWithTorques/CMakeLists.txt b/source/RobotAPI/GraspingWithTorques/CMakeLists.txt
new file mode 100644
index 000000000..17b564c43
--- /dev/null
+++ b/source/RobotAPI/GraspingWithTorques/CMakeLists.txt
@@ -0,0 +1,31 @@
+armarx_set_target("RobotAPI Library: GraspingWithTorques")
+
+
+find_package(Eigen3 QUIET)
+find_package(Simox QUIET)
+
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+armarx_build_if(Simox_FOUND "Simox-VirtualRobot not available")
+
+if (ARMARX_BUILD)
+    include_directories(${Eigen3_INCLUDE_DIR})
+    include_directories(${VirtualRobot_INCLUDE_DIRS})
+
+    set(LIB_NAME       GraspingWithTorques)
+    set(LIB_VERSION    0.1.0)
+    set(LIB_SOVERSION  0)
+
+    set(LIBS RobotAPICore RobotAPIInterfaces ArmarXInterfaces ArmarXCore ArmarXCoreObservers)
+
+    set(LIB_FILES GraspingWithTorques.cpp
+         )
+    set(LIB_HEADERS GraspingWithTorques.h
+         )
+
+    add_library(${LIB_NAME} SHARED ${LIB_FILES} ${LIB_HEADERS})
+
+    library_settings("${LIB_NAME}" "${LIB_VERSION}" "${LIB_SOVERSION}" "${LIB_HEADERS}")
+    target_link_ice(${LIB_NAME})
+    target_link_libraries(${LIB_NAME} ${LIBS})
+endif()
+
diff --git a/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.cpp b/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.cpp
new file mode 100644
index 000000000..fe01e4fd8
--- /dev/null
+++ b/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.cpp
@@ -0,0 +1,294 @@
+/**
+* This file is part of ArmarX.
+*
+* ArmarX is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* ArmarX is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* @package    RobotAPI::GraspingWithTorques
+* @author     Markus Przybylski
+* @date       2014 Markus Przybylski
+
+* @copyright  http://www.gnu.org/licenses/gpl.txt
+*             GNU General Public License
+*/
+
+#include "GraspingWithTorques.h"
+//#include "Armar3GraspContext.h"   //MP: Maybe necessary again later?
+#include "../core/RobotStatechartContext.h" //MP 2014-01-21
+
+//#include "../../units/KinematicUnitHand/KinematicUnitHand.h"
+
+#include <Core/observers/variant/ChannelRef.h>
+#include <Core/observers/variant/SingleTypeVariantList.h>
+#include <Core/robotstate/remote/ArmarPose.h>
+#include <VirtualRobot/IK/DifferentialIK.h>
+
+#include <Core/interface/units/KinematicUnitInterface.h>
+
+#include <RobotAPI/core/RobotStatechartContext.h>
+
+namespace armarx
+{
+    // ****************************************************************
+    // Implementation of StatechartGraspingWithTorques
+    // ****************************************************************
+    void StatechartGraspingWithTorques::defineParameters()
+    {
+        //preshape settings:
+        addToInput("jointAnglesPreshape", VariantType::List(VariantType::Float), false);
+        //how long to wait before switching from preshape to grasp
+        addToInput("timeoutPreshape", VariantType::Float, false);
+
+        //closeHandWithTorques settings:
+        addToInput("jointTorquesGrasp", VariantType::List(VariantType::Float), false);        
+        //Make sure that the joints have time to start moving before we check
+        //low joint velocities as a termination criterion.
+        addToInput("timeoutMinExecutionTime", VariantType::Float, false);
+
+        //installTerminateConditions settings:
+        //how long to wait until you think the hand is closed and grasping is completed
+        addToInput("timeoutGrasp", VariantType::Float, false);
+        addToInput("thresholdVelocity", VariantType::Float, false);
+
+
+        addToInput("robotNodeSetName", VariantType::String, false);        //RobotNodeSet: LeftHand (auskommentarisiert MP 2014-01-21)
+
+        addToLocal("jointNames", VariantType::List(VariantType::String));
+        //addToLocal("jointNames", SingleTypeVariantList(VariantType::String));   //Geht das? (2014-01-21)
+
+        addToLocal("jointVelocityChannel", VariantType::ChannelRef);
+        //addToLocal("jointVelocityChannel", VariantType::ChannelRef, false);
+
+    }
+
+    void StatechartGraspingWithTorques::defineSubstates()
+    {
+        StatePtr statePreshape = addState<StatePreshape>("statePreshape");
+        StatePtr stateCloseHandWithTorques = addState<StateCloseHandWithTorques>("stateCloseHandWithTorques");
+        StatePtr stateInstallTerminateConditions = addState<StateInstallTerminateConditions>("stateInstallTerminateConditions");
+        StatePtr stateSuccess = addState<SuccessState>("stateSuccess");
+        StatePtr stateFailure = addState<FailureState>("stateFailure");
+
+        ParameterMappingPtr mapPreshapeInfo = ParameterMapping::createMapping()
+                ->mapFromParent("jointAnglesPreshape", "jointAnglesPreshape")
+                ->mapFromParent("timeoutPreshape", "timeoutPreshape")
+                ->mapFromParent("jointNames", "jointNames");
+
+        ParameterMappingPtr mapCloseHandWithTorquesInfo = ParameterMapping::createMapping()
+                ->mapFromParent("jointTorquesGrasp", "jointTorquesGrasp")
+                ->mapFromParent("timeoutMinExecutionTime", "timeoutMinExecutionTime")
+                ->mapFromParent("jointNames", "jointNames");
+
+        ParameterMappingPtr mapInstallTerminateConditionsInfo = ParameterMapping::createMapping()
+                ->mapFromParent("timeoutGrasp", "timeoutGrasp")
+                ->mapFromParent("thresholdVelocity", "thresholdVelocity")
+                ->mapFromParent("jointNames")
+                ->mapFromParent("jointVelocityChannel"); //bei gleichem Namen muss man ihn nur einmal angeben
+
+        setInitState(statePreshape, mapPreshapeInfo);
+
+        //transitions
+        addTransition<EvPreshapeTimeout>(statePreshape, stateCloseHandWithTorques, mapCloseHandWithTorquesInfo);
+        addTransition<EvMinExecutionTimeout>(stateCloseHandWithTorques, stateInstallTerminateConditions, mapInstallTerminateConditionsInfo);
+        addTransition<EvGraspTimeout>(stateInstallTerminateConditions, stateFailure);
+        addTransition<EvAllJointVelocitiesLow>(stateInstallTerminateConditions, stateSuccess);
+
+    }
+
+    void StatechartGraspingWithTorques::onEnter()
+    {
+        ARMARX_LOG << eINFO << "Entering StatechartGraspingWithTorques";
+
+        RobotStatechartContext* context = getContext<RobotStatechartContext>();
+        setLocal("jointVelocityChannel", context->getChannelRef(context->getKinematicUnitObserverName(),"jointvelocities"));
+
+        VirtualRobot::RobotNodeSetPtr nodeSet = context->remoteRobot->getRobotNodeSet(getInput<std::string>("robotNodeSetName"));    //woher robotNodeSetName holen? (Argument für getRobotNodeSet())
+
+        SingleTypeVariantList jointNames(VariantType::String);
+
+        for (int i=0; i<nodeSet->getSize(); i++)
+        {
+            jointNames.addVariant(nodeSet->getNode(i)->getName());      //nodes = joints
+        }
+
+        setLocal("jointNames",jointNames);      //befüllen...!?
+    }
+
+    void StatechartGraspingWithTorques::onExit()
+    {
+
+        ARMARX_LOG << eINFO << "Exiting StatechartGraspingWithTorques...";
+
+    }
+
+    // ****************************************************************
+    // Implementation of StatePreshape
+    // ****************************************************************
+
+    void StatePreshape::defineParameters()
+    {
+        addToInput("jointAnglesPreshape", VariantType::List(VariantType::Float), false);
+        addToInput("timeoutPreshape", VariantType::Float, false);
+
+        //addToLocal("jointNames", VariantType::List(VariantType::String));   //ACHTUNG: addToLocal() oder addToInput()? (2013-01-21)
+        addToInput("jointNames", VariantType::List(VariantType::String), false);   //ACHTUNG: addToLocal() oder addToInput()? (2013-01-21)
+    }
+
+    void StatePreshape::onEnter()
+    {
+        ARMARX_LOG << eIMPORTANT << "Entering statePreshape";
+
+        RobotStatechartContext* rsContext = getContext<RobotStatechartContext>();
+        SingleTypeVariantListPtr jointNames = getInput<SingleTypeVariantList>("jointNames");
+        SingleTypeVariantListPtr jointAnglesPreshapeList = getInput<SingleTypeVariantList>("jointAnglesPreshape");
+        //NameValueMap jointAnglesPreshapeMap;
+        NameValueMap jointNamesAndValues;
+
+        if (jointNames->getSize() == jointAnglesPreshapeList->getSize())
+        {
+            for (int j=0; j<jointNames->getSize(); j++)
+            {
+                jointNamesAndValues[jointNames->getVariant(j)->getString()]=jointAnglesPreshapeList->getVariant(j)->getFloat();
+            }
+        }
+        else
+            throw LocalException("StatePreshape: List lengths do not match!");
+
+        //ARMARX_INFO << "node.size()=" << nodes.size() << flush;
+        //ARMARX_INFO << "jointAnglesPreshapeList.size()=" << jointAnglesPreshapeList->getSize() << flush;
+
+        rsContext->kinematicUnitPrx->setJointAngles(jointNamesAndValues);
+
+        ARMARX_LOG << eINFO << "Installing preshape timeout condition";
+        float timeoutPreshape = getInput<float>("timeoutPreshape");
+        condPreshapeTimeout = setTimeoutEvent(timeoutPreshape, createEvent<EvPreshapeTimeout>());
+
+        ARMARX_LOG << eINFO << "Done onEnter()";
+    }
+
+    void StatePreshape::onExit()
+    {
+        removeTimeoutEvent(condPreshapeTimeout);
+        ARMARX_LOG << eIMPORTANT << "StatePreshape: Done onExit()";
+    }
+
+    // ****************************************************************
+    // Implementation of StateCloseHandWithTorques
+    // ****************************************************************
+
+    void StateCloseHandWithTorques::defineParameters()
+    {
+        //closeHandWithTorques settings:
+        addToInput("jointTorquesGrasp", VariantType::List(VariantType::Float), false);
+        addToInput("timeoutMinExecutionTime", VariantType::Float, false);
+
+        addToInput("jointNames", VariantType::List(VariantType::String), false);
+    }
+
+    void StateCloseHandWithTorques::onEnter()
+    {
+        ARMARX_LOG << eIMPORTANT << "Entering stateCloseHandWithTorques";
+
+        RobotStatechartContext* rsContext = getContext<RobotStatechartContext>();
+        SingleTypeVariantListPtr jointNames = getInput<SingleTypeVariantList>("jointNames");
+        SingleTypeVariantListPtr jointTorquesGraspList = getInput<SingleTypeVariantList>("jointTorquesGrasp");
+        NameValueMap jointNamesAndValues;
+
+        if (jointNames->getSize() == jointTorquesGraspList->getSize())
+        {
+            for (int j=0; j<jointNames->getSize(); j++)
+            {
+                jointNamesAndValues[jointNames->getVariant(j)->getString()]=jointTorquesGraspList->getVariant(j)->getFloat();
+            }
+        }
+        else
+            throw LocalException("StateCloseHandWithTorques: List lengths do not match!");
+
+        rsContext->kinematicUnitPrx->setJointTorques(jointNamesAndValues);
+
+        ARMARX_LOG << eINFO << "Installing timeoutMinExecutionTime condition";
+        float timeoutMinExecutionTime = getInput<float>("timeoutMinExecutionTime");
+        condMinimumExecutionTimeout = setTimeoutEvent(timeoutMinExecutionTime, createEvent<EvMinExecutionTimeout>());
+
+        ARMARX_LOG << eIMPORTANT << "Done onEnter()";
+    }
+
+    void StateCloseHandWithTorques::onExit()
+    {
+        removeTimeoutEvent(condMinimumExecutionTimeout);
+    }
+
+    // ****************************************************************
+    // Implementation of StateInstallTerminateConditions
+    // ****************************************************************
+
+    void StateInstallTerminateConditions::defineParameters()
+    {
+        //installTerminateConditions settings:
+        //how long to wait until you think the hand is closed and grasping is completed
+        addToInput("timeoutGrasp", VariantType::Float, false);
+        addToInput("thresholdVelocity", VariantType::Float, false);
+
+        addToInput("jointNames", VariantType::List(VariantType::String), false);
+
+        //addToLocal("jointVelocityChannel", VariantType::ChannelRef);
+        addToInput("jointVelocityChannel", VariantType::ChannelRef, false);
+    }
+
+    void StateInstallTerminateConditions::onEnter()
+    {
+        ARMARX_LOG << eIMPORTANT << "onEnter() stateInstallTerminateConditions";
+
+        ARMARX_LOG << eINFO << "Installing timeoutGrasp condition";
+        float timeoutGrasp = getInput<float>("timeoutGrasp");
+        condGraspTimeout = setTimeoutEvent(timeoutGrasp, createEvent<EvMinExecutionTimeout>());
+
+        ARMARX_LOG << eINFO << "Installing allJointVelocitiesLow condition";
+        float thresholdVelocity = getInput<float>("thresholdVelocity");
+
+        /*
+        Literal JointVelocityLowJoint0(getInput<ChannelRef>("jointVelocityChannel")
+                                       ->getDataFieldIdentifier(getVariant->getString()), "smaller", Literal::createParameterList(thresholdVelocity));  //siehe SingleTypeVariantList, Auslesen mit getInput()
+        Literal JointVelocityLowJoint1(getInput<ChannelRef>(markerChannelName)
+                                      ->getDataFieldIdentifier("localized"), "smaller", Literal::createParameterList(thresholdVelocity));
+        */
+
+        //Term allJointVelocitiesLow = JointVelocityLowJoint0 && JointVelocityLowJoint1;  //TODO: weitere Literale
+        //condAllJointVelocitiesLow = installCondition(allJointVelocitiesLow, createEvent<EvAllJointVelocitiesLow>());
+
+        //TODO: korrekter ChannelName für Hand-/Fingergelenke? Korrekter DatafieldIdentifier?
+        //TODO: Condition zusammenbauen in einer for-Schleife (siehe ArmarX-Doku zu Conditions...)
+        //TODO: korrekte Parametrierung von getDataFieldIdentifier(), mit getInput()...
+
+        Term allJointVelocitiesLow;
+        SingleTypeVariantListPtr jointNamesList = getInput<SingleTypeVariantList>("jointNames");
+        for (int i=0; i<jointNamesList->getSize(); i++)
+        {
+           allJointVelocitiesLow = allJointVelocitiesLow && Literal(getInput<ChannelRef>("jointVelocityChannel")
+                         ->getDataFieldIdentifier(jointNamesList->getVariant(i)->getString()), "smaller", Literal::createParameterList(thresholdVelocity));
+        }
+
+        condAllJointVelocitiesLow = installCondition(allJointVelocitiesLow, createEvent<EvAllJointVelocitiesLow>());
+
+    }
+
+    void StateInstallTerminateConditions::onExit()
+    {
+        ARMARX_LOG << eIMPORTANT << "onExit() stateInstallTerminateConditions";
+        removeTimeoutEvent(condGraspTimeout);
+        removeCondition(condAllJointVelocitiesLow);
+
+    }
+
+}
+
diff --git a/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.h b/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.h
new file mode 100644
index 000000000..998511502
--- /dev/null
+++ b/source/RobotAPI/GraspingWithTorques/GraspingWithTorques.h
@@ -0,0 +1,114 @@
+/**
+* This file is part of ArmarX.
+*
+* ArmarX is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License, or (at your option) any later version.
+*
+* ArmarX is distributed in the hope that it will be useful, but
+* WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* @package    RobotAPI::GraspingWithTorques
+* @author     Markus Przybylski
+* @date       2014 Markus Przybylski
+* @copyright  http://www.gnu.org/licenses/gpl.txt
+*             GNU General Public License
+*/
+
+#ifndef ARMARX_COMPONENT_GRASPINT_WITH_TORQUES_H
+#define ARMARX_COMPONENT_GRASPINT_WITH_TORQUES_H
+
+#include <Core/statechart/Statechart.h>
+
+
+namespace armarx
+{
+    // ****************************************************************
+    // Events
+    // ****************************************************************
+
+    //only for first tests
+    DEFINEEVENT(EvPreshapeTimeout)
+    DEFINEEVENT(EvMinExecutionTimeout)
+    DEFINEEVENT(EvGraspTimeout)
+    DEFINEEVENT(EvAllJointVelocitiesLow)
+
+    // ****************************************************************
+    // Definition of StatechartGraspingWithTorques
+    // ****************************************************************
+    struct StatechartGraspingWithTorques :
+        StateTemplate<StatechartGraspingWithTorques>
+    {
+        void defineParameters();
+        void defineSubstates();
+        void onEnter();
+        void onExit();
+
+    };
+
+
+
+    // ****************************************************************
+    // Definition of StatePreshape
+    // ****************************************************************
+    /**
+     * StatePreshape: Move the fingers to a preshape configuration, then wait a little.
+     */
+
+    struct StatePreshape :
+        StateTemplate<StatePreshape>
+    {
+        void defineParameters();
+        void onEnter();
+        void onExit();
+
+        StateUtility::ActionEventIdentifier condPreshapeTimeout;
+    };
+
+    // ****************************************************************
+    // Definition of StateCloseHandWithTorques
+    // ****************************************************************
+
+    /**
+     * StateCloseHandWithTorques: Put torques on the hand's joints.
+     */
+    struct StateCloseHandWithTorques :
+        StateTemplate<StateCloseHandWithTorques>
+    {
+        void defineParameters();
+        void onEnter();
+        void onExit();
+
+        //Make sure that the joints have time to start moving before we check
+        //low joint velocities as a termination criterion.
+        StateUtility::ActionEventIdentifier condMinimumExecutionTimeout;
+    };
+
+    // ****************************************************************
+    // Definition of StateInstallTerminateConditions
+    // ****************************************************************
+    /**
+     * StateInstallTerminateConditions:
+     */
+
+    struct StateInstallTerminateConditions :
+        StateTemplate<StateInstallTerminateConditions>
+    {
+        void defineParameters();
+        void onEnter();
+        void onExit();
+
+        ConditionIdentifier condAllJointVelocitiesLow;
+        StateUtility::ActionEventIdentifier condGraspTimeout;
+    };
+
+
+}
+
+#endif
-- 
GitLab