From 6ed38ae4b6448ea2127521e91636f9d9e9e1223a Mon Sep 17 00:00:00 2001
From: Nikolaus Vahrenkamp <vahrenkamp@kit.edu>
Date: Mon, 18 Aug 2014 13:36:08 +0200
Subject: [PATCH] initial version of place object statechart

---
 source/RobotAPI/statecharts/CMakeLists.txt    |   1 +
 .../statecharts/PlaceObject/CMakeLists.txt    |  26 ++
 .../statecharts/PlaceObject/PlaceObject.cpp   | 318 ++++++++++++++++++
 .../statecharts/PlaceObject/PlaceObject.h     |  85 +++++
 4 files changed, 430 insertions(+)
 create mode 100644 source/RobotAPI/statecharts/PlaceObject/CMakeLists.txt
 create mode 100644 source/RobotAPI/statecharts/PlaceObject/PlaceObject.cpp
 create mode 100644 source/RobotAPI/statecharts/PlaceObject/PlaceObject.h

diff --git a/source/RobotAPI/statecharts/CMakeLists.txt b/source/RobotAPI/statecharts/CMakeLists.txt
index bcb3ae3b2..b5fcf48db 100644
--- a/source/RobotAPI/statecharts/CMakeLists.txt
+++ b/source/RobotAPI/statecharts/CMakeLists.txt
@@ -2,3 +2,4 @@ add_subdirectory(GraspingWithTorques)
 add_subdirectory(OpenHand)
 add_subdirectory(MovePlatform)
 add_subdirectory(MovePlatformToLandmark)
+add_subdirectory(PlaceObject)
diff --git a/source/RobotAPI/statecharts/PlaceObject/CMakeLists.txt b/source/RobotAPI/statecharts/PlaceObject/CMakeLists.txt
new file mode 100644
index 000000000..6a81c9bd8
--- /dev/null
+++ b/source/RobotAPI/statecharts/PlaceObject/CMakeLists.txt
@@ -0,0 +1,26 @@
+armarx_set_target("RobotAPI Library: PlaceObject")
+
+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 (Eigen3_FOUND AND Simox_FOUND)
+    include_directories(
+        ${Eigen3_INCLUDE_DIR}
+        ${Simox_INCLUDE_DIRS})
+endif()
+
+set(LIB_NAME       PlaceObject)
+set(LIB_VERSION    0.1.0)
+set(LIB_SOVERSION  0)
+
+set(LIBS RobotAPICore RobotAPIInterfaces ArmarXInterfaces ArmarXCore ArmarXCoreObservers)
+
+set(LIB_FILES PlaceObject.cpp
+     )
+set(LIB_HEADERS PlaceObject.h
+     )
+
+armarx_add_library("${LIB_NAME}" "${LIB_VERSION}" "${LIB_SOVERSION}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
diff --git a/source/RobotAPI/statecharts/PlaceObject/PlaceObject.cpp b/source/RobotAPI/statecharts/PlaceObject/PlaceObject.cpp
new file mode 100644
index 000000000..b0c5867a9
--- /dev/null
+++ b/source/RobotAPI/statecharts/PlaceObject/PlaceObject.cpp
@@ -0,0 +1,318 @@
+/*
+* 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::PlaceObject
+* @author     Nikolaus Vahrenkamp
+* @date       2014 
+
+* @copyright  http://www.gnu.org/licenses/gpl.txt
+*             GNU General Public License
+*/
+
+#include "PlaceObject.h"
+#include "../../core/RobotStatechartContext.h"
+
+#include <Core/observers/variant/ChannelRef.h>
+#include <Core/observers/variant/SingleTypeVariantList.h>
+#include <RobotAPI/robotstate/remote/ArmarPose.h>
+#include <VirtualRobot/IK/DifferentialIK.h>
+
+#include <RobotAPI/interface/units/KinematicUnitInterface.h>
+
+#include <RobotAPI/core/RobotStatechartContext.h>
+
+namespace armarx
+{
+    // ****************************************************************
+    // Implementation of StatechartPlaceObject
+    // ****************************************************************
+    void StatechartPlaceObject::defineParameters()
+    {
+        addToInput("maxHeightToMoveDown", VariantType::List(VariantType::Float), false);
+        addToInput("minForceForSuccess", VariantType::List(VariantType::Float), false);
+        addToInput("timeoutPlaceObject", VariantType::Float, false);
+ 
+        addToInput("robotNodeSetName", VariantType::String, false);
+        addToInput("robotBaseFrame", VariantType::String, false);
+
+
+        addToLocal("startPose", VariantType::List(VariantType::FramedPose));
+        addToLocal("goalPose", VariantType::List(VariantType::FramedPose));
+
+        //addToLocal("jointNames", VariantType::List(VariantType::String));
+        //addToLocal("jointVelocitiesDatafields", VariantType::List(VariantType::DatafieldRef));
+    }
+
+    void StatechartPlaceObject::defineSubstates()
+    {
+        StatePtr stateMoveDown= addState<StateMoveDown>("stateMoveDown");
+        //StatePtr stateCheckForces = addState<StateCheckForces>("stateCheckForces");
+        StatePtr stateSuccess = addState<SuccessState>("stateSuccess");
+        StatePtr stateFailure = addState<FailureState>("stateFailure");
+
+        ParameterMappingPtr mapMoveDown = ParameterMapping::createMapping()
+                ->mapFromParent("*", "*");
+        //ParameterMappingPtr mapCheckForces = ParameterMapping::createMapping()
+        //        ->mapFromParent("*", "*");
+
+        setInitState(stateMoveDown, mapMoveDown);
+
+        //transitions
+        addTransition<EvSuccess>(stateMoveDown, stateMoveDown);
+        addTransition<EvFailure>(stateMoveDown, stateFailure);
+        //addTransition<EvSuccess>(stateCheckForces, stateSuccess);
+        //addTransition<EvFailure>(stateCheckForces, stateMoveDown);
+
+        addTransition<EvPlaceObjectCollision>(stateMoveDown, stateSuccess);
+        //addTransition<EvPlaceObjectTimeout>(stateCheckForces, stateFailure);
+
+    }
+
+    void StatechartPlaceObject::onEnter()
+    {
+        ARMARX_DEBUG << "Entering StatechartPlaceObject";
+
+        RobotStatechartContext* context = getContext<RobotStatechartContext>();
+        //setLocal("jointVelocityChannel", context->getChannelRef(context->getKinematicUnitObserverName(),"jointvelocities"));
+        //ChannelRefPtr tempChannelRef = context->getChannelRef(context->getKinematicUnitObserverName(),"jointvelocities");
+
+        std::string rnsName = getInput<std::string>("robotNodeSetName");
+        std::string rnBaseName = getInput<std::string>("robotBaseFrame");
+        VirtualRobot::RobotNodeSetPtr nodeSet = context->remoteRobot->getRobotNodeSet(rnsName);
+        if (!nodeSet)
+        {
+            throw UserException("RobotNodeSet not found: " + rnsName);
+        }
+        if (!nodeSet->getTCP())
+        {
+            throw UserException("RobotNodeSet without tcp: " + rnsName);
+        }
+        VirtualRobot::RobotNodePtr nodeBase = context->remoteRobot->getRobotNode(rnBaseName);
+        if (!nodeBase)
+        {
+            throw UserException("RobotNode not found: " + rnBaseName);
+        }
+
+        Eigen::Matrix4f tcpPose = nodeSet->getTCP()->getGlobalPose();
+        tcpPose = nodeBase->toLocalCoordinateSystem(tcpPose);
+        FramedPosePtr fp(new FramedPose(tcpPose,rnBaseName));
+
+        setLocal("startPose", fp);
+
+        Eigen::Matrix4f tcpGoalPose = nodeSet->getTCP()->getGlobalPose();
+        float maxHeight = getInput<float>("maxHeightToMoveDown");
+        tcpGoalPose(0,3) -= maxHeight;
+        tcpGoalPose = nodeBase->toLocalCoordinateSystem(tcpGoalPose);
+        FramedPosePtr fpGoal(new FramedPose(tcpGoalPose,rnBaseName));
+
+        setLocal("goalPose", fpGoal);
+
+        ARMARX_LOG << eINFO << "Installing place object timeout condition";
+        float timeoutPlaceObject = getInput<float>("timeoutPlaceObject");
+
+        condPlaceObjectTimeout = setTimeoutEvent(timeoutPlaceObject, createEvent<EvPlaceObjectTimeout>());
+
+
+
+        // install the force condition
+        float force = getInput<float>("minForceForSuccess");
+        Term cond;
+        for(unsigned int i=0; i<nodeSet->getSize(); i++)
+        {
+            ParameterList inrangeCheck;
+            inrangeCheck.push_back(new Variant(-force));
+            inrangeCheck.push_back(new Variant(force));
+
+            Literal inrangeLiteral(DataFieldIdentifier(context->getKinematicUnitObserverName(),"jointtorques", nodeSet->getNode(i)->getName()), "inrange", inrangeCheck);
+            cond = cond && !inrangeLiteral;
+        }
+
+        condPlaceObjectCollision = installCondition<EvPlaceObjectCollision>(cond);
+    }
+
+    void StatechartPlaceObject::onExit()
+    {
+        removeTimeoutEvent(condPlaceObjectTimeout);
+        removeCondition(condPlaceObjectCollision);
+
+        ARMARX_LOG << eINFO << "Exiting StatechartPlaceObject...";
+    }
+
+    // ****************************************************************
+    // Implementation of StateMoveDown
+    // ****************************************************************
+
+    void StateMoveDown::defineParameters()
+    {
+        addToInput("maxHeightToMoveDown", VariantType::List(VariantType::Float), false);
+        addToInput("minForceForSuccess", VariantType::List(VariantType::Float), false);
+        addToInput("timeoutPlaceObject", VariantType::Float, false);
+        addToInput("robotNodeSetName", VariantType::String, false);
+        addToInput("robotBaseFrame", VariantType::String, false);
+        addToInput("startPose", VariantType::List(VariantType::FramedPose), false);
+    }
+
+    void StateMoveDown::onEnter()
+    {
+        ARMARX_DEBUG << "Entering StateMoveDown" << flush;
+
+        RobotStatechartContext* rsContext = getContext<RobotStatechartContext>();
+        std::string rnsName = getInput<std::string>("robotNodeSetName");
+        std::string rnBaseName = getInput<std::string>("robotBaseFrame");
+        VirtualRobot::RobotPtr localRobot = RemoteRobot::createLocalClone(rsContext->robotStateComponent);
+
+        VirtualRobot::RobotNodeSetPtr nodeSet = localRobot->getRobotNodeSet(rnsName);
+        VirtualRobot::RobotNodePtr nodeBase = localRobot->getRobotNode(rnBaseName);
+        FramedPosePtr startPoseFramed = getInput<FramedPose>("startPose");
+        FramedPosePtr goalPoseFramed = getInput<FramedPose>("goalPose");
+
+        Eigen::Matrix4f startPose = startPoseFramed->toEigen();
+        Eigen::Matrix4f goalPose = goalPoseFramed->toEigen();
+        Eigen::Matrix4f currentPose = nodeSet->getTCP()->getGlobalPose();
+        currentPose = nodeBase->toLocalCoordinateSystem(currentPose);
+
+        ARMARX_DEBUG << "startPose (coordsystem " << rnBaseName << ") : " << startPose << flush;
+        ARMARX_DEBUG << "goalPose (coordsystem " << rnBaseName << ") : " << goalPose << flush;
+        ARMARX_DEBUG << "currentPose (coordsystem " << rnBaseName << ") : " << currentPose << flush;
+
+        float dist = (goalPose.block(0,3,3,1) - currentPose.block(0,3,3,1)).norm();
+        if (dist<10.0f)
+        {
+            ARMARX_ERROR << "Did not hit any surface, sending failure event..." << flush;
+            sendEvent<EvFailure>();
+        }
+
+
+        VirtualRobot::DifferentialIKPtr ikSolver(new VirtualRobot::DifferentialIK(nodeSet,nodeBase));
+
+        ikSolver->setGoal(goalPose,nodeSet->getTCP(),VirtualRobot::IKSolver::Position,10.0f);
+
+        bool ikOK = ikSolver->solveIK(0.6f,0,10);
+
+        if (!ikOK)
+        {
+            ARMARX_ERROR << "No IK solution for goal pose (coordsystem " << rnBaseName << ") : " << goalPose << flush;
+            sendEvent<EvFailure>();
+        }
+
+        std::vector<float> jointValues = nodeSet->getJointValues();
+        NameValueMap jointNamesAndValues;
+
+        for (unsigned int j=0; j<jointValues.size(); j++)
+        {
+            jointNamesAndValues[nodeSet->getNode(j)->getName()]=jointValues[j];
+            ARMARX_DEBUG << "target for joint :" << nodeSet->getNode(j)->getName() << " -> " << jointValues[j] << flush;
+        }
+
+        rsContext->kinematicUnitPrx->setJointAngles(jointNamesAndValues);
+
+        ARMARX_DEBUG << "StateMoveDown: Done onEnter()";
+    }
+
+    void StateMoveDown::onExit()
+    {
+        ARMARX_DEBUG << "StatePlaceObject: Done onExit()";
+    }
+
+
+    // ****************************************************************
+    // Implementation of StateCheckForces
+    // ****************************************************************
+/*
+    void StateCheckForces::defineParameters()
+    {
+        addToInput("maxHeightToMoveDown", VariantType::List(VariantType::Float), false);
+        addToInput("minForceForSuccess", VariantType::List(VariantType::Float), false);
+        addToInput("timeoutPlaceObject", VariantType::Float, false);
+        addToInput("robotNodeSetName", VariantType::String, false);
+        addToInput("robotBaseFrame", VariantType::String, false);
+        addToInput("startPose", VariantType::List(VariantType::FramedPose), false);
+    }
+
+    void StateCheckForces::onEnter()
+    {
+        ARMARX_DEBUG << "Entering StateCheckForces" << flush;
+
+        float force = getInput<float>("minForceForSuccess");
+        RobotStatechartContext* rsContext = getContext<RobotStatechartContext>();
+        rsContext->kinematicUnitObserverPrx->getDataFields()
+
+
+        RobotStatechartContext* rsContext = getContext<RobotStatechartContext>();
+        std::string rnsName = getInput<std::string>("robotNodeSetName");
+        std::string rnBaseName = getInput<std::string>("robotBaseFrame");
+
+
+        VirtualRobot::RobotPtr localRobot = RemoteRobot::createLocalClone(context->robotStateComponent);
+        std::string rnsName = getInput<std::string>("robotNodeSetName");
+        std::string rnBaseName = getInput<std::string>("robotBaseFrame");
+        VirtualRobot::RobotNodeSetPtr nodeSet = localRobot->getRobotNodeSet(rnsName);
+        VirtualRobot::RobotNodePtr nodeBase = localRobot->getRobotNode(rnBaseName);
+        FramedPosePtr startPoseFramed = getInput<FramedPose>("startPose");
+        FramedPosePtr goalPoseFramed = getInput<FramedPose>("goalPose");
+
+        Eigen::Matrix4f startPose = startPoseFramed->toEigen();
+        Eigen::Matrix4f goalPose = goalPoseFramed->toEigen();
+        Eigen::Matrix4f currentPose = nodeSet->getTCP()->getGlobalPose();
+        currentPose = nodeBase->toLocalCoordinateSystem(currentPose);
+
+        ARMARX_DEBUG << "startPose (coordsystem " << rnBaseName << ") : " << startPose << flush;
+        ARMARX_DEBUG << "goalPose (coordsystem " << rnBaseName << ") : " << goalPose << flush;
+        ARMARX_DEBUG << "currentPose (coordsystem " << rnBaseName << ") : " << currentPose << flush;
+
+        float dist = (goalPose.block(0,3,3,1) - currentPose.block(0,3,3,1)).norm();
+        if (dist<10.0f)
+        {
+            ARMARX_ERROR << "Did not hit any surface, sending failure event..." << flush;
+            sendEvent<EvFailure>();
+        }
+
+
+        VirtualRobot::DifferentialIKPtr ikSolver(new VirtualRobot::DifferentialIKPtr(nodeSet,nodeBase));
+
+        ikSolver->setGoal(goalPose,nodeSet->getTCP(),VirtualRobot::IKSolver::Position,10.0f);
+
+        bool ikOK = ikSolver->solveIK(0.6f,0,10);
+
+        if (!ikOK)
+        {
+            ARMARX_ERROR << "No IK solution for goal pose (coordsystem " << rnBaseName << ") : " << goalPose << flush;
+            sendEvent<EvFailure>();
+        }
+
+        std::vector<float> jointValues = nodeSet->getJointValues();
+        NameValueMap jointNamesAndValues;
+
+        for (unsigned int j=0; j<jointValues->getSize(); j++)
+        {
+            jointNamesAndValues[nodeSet->getNode(j)->getName()]=jointValues[j];
+            ARMARX_DEBUG << "target for joint :" << nodeSet->getNode(j)->getName() << " -> " << jointValues[j] << flush;
+        }
+
+        rsContext->kinematicUnitPrx->setJointAngles(jointNamesAndValues);
+
+        ARMARX_DEBUG << "StateCheckForces: Done onEnter()";
+    }
+
+    void StateCheckForces::onExit()
+    {
+        ARMARX_DEBUG << "StateCheckForces: Done onExit()";
+    }
+
+*/
+
+}
+
diff --git a/source/RobotAPI/statecharts/PlaceObject/PlaceObject.h b/source/RobotAPI/statecharts/PlaceObject/PlaceObject.h
new file mode 100644
index 000000000..5e3eac026
--- /dev/null
+++ b/source/RobotAPI/statecharts/PlaceObject/PlaceObject.h
@@ -0,0 +1,85 @@
+/*
+* 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::PlaceObject
+* @author     Nikolaus Vahrenkamp
+* @date       2014
+* @copyright  http://www.gnu.org/licenses/gpl.txt
+*             GNU General Public License
+*/
+
+#ifndef ARMARX_COMPONENT_PLACE_OBJECT_H
+#define ARMARX_COMPONENT_PLACE_OBJECT_H
+
+#include <Core/statechart/Statechart.h>
+
+
+namespace armarx
+{
+    // ****************************************************************
+    // Events
+    // ****************************************************************
+
+    DEFINEEVENT(EvPlaceObjectTimeout)
+    DEFINEEVENT(EvPlaceObjectCollision)
+
+
+    // ****************************************************************
+    // Definition of StatechartPlaceObject
+    // ****************************************************************
+    struct StatechartPlaceObject :
+        StateTemplate<StatechartPlaceObject>
+    {
+        void defineParameters();
+        void defineSubstates();
+        void onEnter();
+        void onExit();
+        StateUtility::ActionEventIdentifier condPlaceObjectTimeout;
+        ConditionIdentifier condPlaceObjectCollision;
+    };
+
+
+
+    // ****************************************************************
+    // Definition of states
+    // ****************************************************************
+    /**
+     * StatePlaceMoveDown: Move down until a surface is hit
+     */
+
+    struct StateMoveDown :
+        StateTemplate<StateMoveDown>
+    {
+        void defineParameters();
+        void onEnter();
+        void onExit();
+    };
+
+
+    /**
+     * StateCheckForces: Check if a surface was hit -> forces must increase
+     */
+    /*struct StateCheckForces :
+        StateTemplate<StateCheckForces>
+    {
+        void defineParameters();
+        void onEnter();
+        void onExit();
+    };*/
+
+}
+
+#endif
-- 
GitLab