blob: 194ca0e15e417a001987b42fc4a3ed36aa4e67fc [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 "ROSManager.h"
#include <ros/ros.h>
#include <extevhandlerhelper.h>
#include "EXECUTE_ACTION_SERVER.h"
#ifdef FORTE_ENABLE_GENERATED_SOURCE_CPP
#include "EXECUTE_ACTION_SERVER_gen.cpp"
#endif
DEFINE_FIRMWARE_FB(FORTE_EXECUTE_ACTION_SERVER, g_nStringIdEXECUTE_ACTION_SERVER)
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anDataInputNames[] = { g_nStringIdQI, g_nStringIdACTIONNAMESPACE, g_nStringIdACTIONMSGNAME, g_nStringIdRESULT, g_nStringIdID, g_nStringIdSTATE };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anDataInputTypeIds[] = { g_nStringIdBOOL, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdDINT, g_nStringIdSTRING };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anDataOutputNames[] = { g_nStringIdQO, g_nStringIdFBSTATUS, g_nStringIdACTIONSTATUS, g_nStringIdCOMMAND, g_nStringIdID1, g_nStringIdID2 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anDataOutputTypeIds[] = { g_nStringIdBOOL, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdSTRING, g_nStringIdDINT, g_nStringIdDINT };
const TForteInt16 FORTE_EXECUTE_ACTION_SERVER::scm_anEIWithIndexes[] = { 0, 4 };
const TDataIOID FORTE_EXECUTE_ACTION_SERVER::scm_anEIWith[] = { 0, 1, 2, 255, 0, 5, 4, 3, 255 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anEventInputNames[] = { g_nStringIdINIT, g_nStringIdRSP };
const TDataIOID FORTE_EXECUTE_ACTION_SERVER::scm_anEOWith[] = { 0, 1, 255, 0, 1, 3, 2, 4, 5, 255 };
const TForteInt16 FORTE_EXECUTE_ACTION_SERVER::scm_anEOWithIndexes[] = { 0, 3, -1 };
const CStringDictionary::TStringId FORTE_EXECUTE_ACTION_SERVER::scm_anEventOutputNames[] = { g_nStringIdINITO, g_nStringIdIND };
const SFBInterfaceSpec FORTE_EXECUTE_ACTION_SERVER::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_SERVER::executeEvent(int pa_nEIID){
switch (pa_nEIID){
case scm_nEventINITID:
if(QI() && !m_Initiated){
m_RosNamespace = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(ACTIONNAMESPACE());
m_RosMsgName = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(ACTIONMSGNAME());
DEVLOG_DEBUG("[EXEC_SERVER] Namespace: %s \n[EXEC_SERVER] Message name : %s \n", m_RosNamespace.c_str(), m_RosMsgName.c_str());
m_nh = new ros::NodeHandle(m_RosNamespace);
m_ActionServer = new actionServer(*m_nh, m_RosMsgName, boost::bind(&FORTE_EXECUTE_ACTION_SERVER::ActionExecuteCB, this, _1), false);
m_ActionServer->start(); //not needed if auto_start=true (last param in ctor of server)
QO() = true;
m_Initiated = true;
FBSTATUS() = "Server started";
}
//server already initialized
else if(QI() && m_Initiated){
FBSTATUS() = "Server already initialized";
QO() = true;
}
//terminate server and function block
else{
m_Initiated = false;
m_ResultAvailable = false;
if(m_ActionServer->isActive()){
m_ActionServer->setAborted();
}
m_ActionServer->shutdown(); //TODO test this!
//ros::shutdown();
FBSTATUS() = "Action Server Shutdown";
//DEVLOG_DEBUG("[EXEC_SERVER] Action server shutdown\n");
}
sendOutputEvent(scm_nEventINITOID);
break;
case scm_nEventRSPID:
//send a result (see executeCB)
if(QI()){
m_Result.result = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(RESULT());
m_Result.id = ID();
FBSTATUS() = "Server sends result";
m_ResultAvailable = true;
}
//send feedback
else{
// get feedback data from STATE() input
m_Feedback.state = getExtEvHandler<CROSManager>(*this).ciecStringToStdString(STATE());
m_ActionServer->publishFeedback(m_Feedback);
}
break;
//The server received a new goal
case cg_nExternalEventID:
if(m_ActionServer->isPreemptRequested() || !ros::ok()){
m_ActionServer->setPreempted();
ACTIONSTATUS() = "PREEMPTED";
QO() = false;
//DEVLOG_DEBUG("[EXEC_SERVER] ExternalEvent: preempted or !ok\n");
}
else{
int stringLength = std::strlen(m_GoalConstPtr->command.c_str());
CIEC_STRING tmpResult;
tmpResult.assign(m_GoalConstPtr->command.c_str(), static_cast<TForteUInt16>(stringLength));
COMMAND().saveAssign(tmpResult);
ID1() = m_GoalConstPtr->id1;
ID2() = m_GoalConstPtr->id2;
FBSTATUS() = "Server received new goal";
ACTIONSTATUS() = "ACTIVE";
QO() = true;
}
sendOutputEvent(scm_nEventINDID);
break;
}
}
void FORTE_EXECUTE_ACTION_SERVER::ActionExecuteCB(const ExecuteGoalConstPtr &pa_goal){
m_GoalConstPtr = pa_goal;
ros::Rate r(2); //2Hz
setEventChainExecutor(m_poInvokingExecEnv);
//DEVLOG_DEBUG("[EXEC_SERVER] Received goal is: %s \n", mGoalConstPtr->command.c_str());
getExtEvHandler<CROSManager>(*this).startChain(this);
// FIXME better idea as flag polling?
//wait for an available result(mResultAvailable set in case of RSP+)
while(!m_ResultAvailable && m_Initiated){
// send cyclic feedback here if needed
// mActionServer->publishFeedback(mFeedback);
r.sleep();
}
m_ResultAvailable = false;
m_ActionServer->setSucceeded(m_Result);
//DEVLOG_DEBUG("[EXEC_SERVER] result is: %s \n", mResult.result.c_str());
FBSTATUS() = "Server has sent result for current goal";
ACTIONSTATUS() = "SUCCEEDED";
}