blob: ba910463150d2ad3c8683080d8d5d800cc34c8dc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 - 2017 fortiss GmbH
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Ben Schneider
* - initial implementation and documentation
*******************************************************************************/
#include <ros/ros.h>
#include "ROSManager.h"
#include <extevhandlerhelper.h>
#include "EXECUTE_ACTION_CLIENT.h"
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "EXECUTE_ACTION_CLIENT_gen.cpp"
#endif
DEFINE_FIRMWARE_FB(FORTE_EXECUTE_ACTION_CLIENT, g_nStringIdEXECUTE_ACTION_CLIENT)
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anDataInputNames[] = { g_nStringIdQI, g_nStringIdACTIONNAMESPACE, g_nStringIdACTIONMSGNAME, g_nStringIdCOMMAND, g_nStringIdID1, g_nStringIdID2 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anDataInputTypeIds[] = { g_nStringIdBOOL, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdDINT, g_nStringIdDINT };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anDataOutputNames[] = { g_nStringIdQO, g_nStringIdFBSTATUS, g_nStringIdACTIONSTATUS, g_nStringIdRESULT, g_nStringIdID, g_nStringIdSTATE };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anDataOutputTypeIds[] = { g_nStringIdBOOL, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdDINT, g_nStringIdSTRING };
const TForteInt16 FORTE_EXECUTE_ACTION_CLIENT::scm_anEIWithIndexes[] = { 0, 4 };
const TDataIOID FORTE_EXECUTE_ACTION_CLIENT::scm_anEIWith[] = { 0, 1, 2, 255, 0, 3, 4, 5, 255 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anEventInputNames[] = { g_nStringIdINIT, g_nStringIdREQ };
const TDataIOID FORTE_EXECUTE_ACTION_CLIENT::scm_anEOWith[] = { 0, 1, 255, 0, 1, 2, 4, 3, 255, 5, 255 };
const TForteInt16 FORTE_EXECUTE_ACTION_CLIENT::scm_anEOWithIndexes[] = { 0, 3, 9 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_CLIENT::scm_anEventOutputNames[] = { g_nStringIdINITO, g_nStringIdCNF };
const SFBInterfaceSpec FORTE_EXECUTE_ACTION_CLIENT::scm_stFBInterfaceSpec = { 2, scm_anEventInputNames, scm_anEIWith, scm_anEIWithIndexes, 2, scm_anEventOutputNames, scm_anEOWith, scm_anEOWithIndexes, 6, scm_anDataInputNames, scm_anDataInputTypeIds, 6, scm_anDataOutputNames, scm_anDataOutputTypeIds, 0, 0 };
void FORTE_EXECUTE_ACTION_CLIENT::executeEvent(int pa_nEIID){
switch (pa_nEIID){
case scm_nEventINITID:
//initialize FB
if(!m_Initiated){
connectToActionServer();
QO() = true;
}
//already initialized
else if(QI() && m_Initiated){
FBSTATUS() = "Already initiated";
QO() = true;
}
//termintate FB
else if(!QI() && m_Initiated){
m_ActionClient->cancelAllGoals();
ros::shutdown();
m_Initiated = false;
FBSTATUS() = "Terminated - All goals canceled";
QO() = false;
}
sendOutputEvent(scm_nEventINITOID);
break;
case scm_nEventREQID:
//send new goal to the action server
if(m_Initiated){
//send new goal
if(QI() && !m_GoalActive){
if(m_ActionClient->isServerConnected()){
//register the external eventchain on the thread of the Request event
setEventChainExecutor(m_poInvokingExecEnv);
reapp_msgs::ExecuteGoal goal;
goal.id1 = ID1();
goal.id2 = ID2();
goal.command = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(COMMAND());
m_ActionClient->sendGoal(goal, boost::bind(&FORTE_EXECUTE_ACTION_CLIENT::doneCallback, this, _1, _2), boost::bind(&FORTE_EXECUTE_ACTION_CLIENT::activeCallback, this), boost::bind(&FORTE_EXECUTE_ACTION_CLIENT::feedbackCallback, this, _1));
FBSTATUS() = "New action goal sent";
QO() = true;
}
else{ //not connected
FBSTATUS() = "Sending goal not possible. Server not Connected";
QO() = false;
}
}
//ignore goals that are sent while another goal is active
else if(!QI() && !m_GoalActive){
FBSTATUS() = "Goal not sent, server busy";
}
//cancel the goal at the action server that was sent by the client
else if(!QI() && m_GoalActive){
FBSTATUS() = "Canceling goals";
m_ActionClient->cancelAllGoals();
FBSTATUS() = "Goals canceled";
QO() = false;
sendOutputEvent(scm_nEventCNFID);
}
}
//FB is not initiated at all/correctly
else{
FBSTATUS() = "FB not initiated";
QO() = false;
}
break;
case cg_nExternalEventID:
//we received feedback (QO=false)
if(false == QO()){
const std::string callbackFeedback = m_ExecuteFeedbackConstPtr->state;
STATE() = callbackFeedback.c_str();
FBSTATUS() = "Feedback received";
}
//we received a result (QO=true)
else{
const std::string callbackResultResult = m_ExecuteResultConstPtr->result;
const int callbackResultID = m_ExecuteResultConstPtr->id;
ID() = callbackResultID;
RESULT() = callbackResultResult.c_str();
ACTIONSTATUS() = getCurrentActionState().c_str();
FBSTATUS() = "Result received";
}
sendOutputEvent(scm_nEventCNFID);
break;
}
}
void FORTE_EXECUTE_ACTION_CLIENT::doneCallback(const actionlib::SimpleClientGoalState&, const ExecuteResultConstPtr& pa_result){
m_ExecuteResultConstPtr = pa_result;
ACTIONSTATUS() = getCurrentActionState().c_str();
QO() = true;
m_GoalActive = false;
getExtEvHandler<CROSManager>(*this).startChain(this);
}
void FORTE_EXECUTE_ACTION_CLIENT::activeCallback(){
ACTIONSTATUS() = getCurrentActionState().c_str();
m_GoalActive = true;
}
void FORTE_EXECUTE_ACTION_CLIENT::feedbackCallback(const ExecuteFeedbackConstPtr &pa_feedback){
m_ExecuteFeedbackConstPtr = pa_feedback;
ACTIONSTATUS() = getCurrentActionState().c_str();
QO() = false;
getExtEvHandler<CROSManager>(*this).startChain(this);
}
std::string FORTE_EXECUTE_ACTION_CLIENT::getCurrentActionState(){
std::string retVal = "UNKNOWN";
int i = m_ActionClient->getState().state_;
switch (i){
case actionlib::SimpleClientGoalState::PENDING:
retVal = "PENDING";
break;
case actionlib::SimpleClientGoalState::ACTIVE:
retVal = "ACTIVE";
break;
case actionlib::SimpleClientGoalState::PREEMPTED:
retVal = "PREEMPTED";
break;
case actionlib::SimpleClientGoalState::SUCCEEDED:
retVal = "SUCCEEDED";
break;
case actionlib::SimpleClientGoalState::ABORTED:
case actionlib::SimpleClientGoalState::REJECTED:
retVal = "ABORTED";
break;
case actionlib::SimpleClientGoalState::RECALLED:
retVal = "RECALLED";
break;
case actionlib::SimpleClientGoalState::LOST:
retVal = "LOST";
break;
}
return retVal;
}
void FORTE_EXECUTE_ACTION_CLIENT::connectToActionServer(){
m_RosNamespace = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(ACTIONNAMESPACE());
m_RosMsgName = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(ACTIONMSGNAME());
DEVLOG_DEBUG("[EXEC_CLIENT] Namespace: %s \nMessage name : %s \n", m_RosNamespace.c_str(), m_RosMsgName.c_str());
nh = new ros::NodeHandle(m_RosNamespace);
m_ActionClient = new actionClient(*nh, m_RosMsgName, true);
FBSTATUS() = "Client waits for server";
m_ActionClient->waitForServer();
FBSTATUS() = "Client connected to server";
m_Initiated = true;
}